banner



How To Find Out Whether You Are Signed Up For Selective Service

How YOU can Acquire Mock testing in .NET Core and C# with Moq

Follow me on Twitter, happy to take your suggestions on topics or improvements /Chris

When we test we just want to test one thing - the business logic of the method. Ofttimes our method needs the help of dependencies to be able to bear out its job properly. Depending on what these dependencies answer - there might be several paths through a method. So what is Mock testing? It's about testing just i thing, in isolation, past mocking how your dependencies should behave.

In this article we will encompass the following:

  • Why test, it's important to understand why we test our code. Is it to ensure our code works? Or possibly nosotros are adding tests for defensive reasons so that future refactors don't mess up the concern logic?
  • What to test, normally this question has many answers. We want to ensure that our method does what it says it does, e.g i+one equals 2. We might besides want to ensure that we test all the different paths through the method, the happy path besides equally alternate/erroneous paths. Lastly, nosotros might want to assert that a certain behavior takes place.
  • Demo, let'southward write some code that has more i execution path and introduce the Mocking library Moq and come across how it tin can help us fulfill the above.

References

  • xUnit testing This folio describes how to use xUnit with .Internet Core

  • nUnit testing This page describes how to utilise nUnit with .Net Core.

  • dotnet exam, terminal control description This page describes the terminal command dotnet test and all the different arguments y'all tin telephone call information technology with.

  • dotnet selective test This page describes how to do selective testing and how to gear up filters and query using filters.

  • Get started with C# and VS Code

  • .Cyberspace Core Serial on NuGet, Serverless and much more

  • Moq tutorial This is the GitHub repo for the Moq library. The README contains a tutorial.

Why test

As we mentioned already at that place are many answers to this question. Then how practise nosotros know? Well, I commonly see the following reasons:

  • Ensuring Quality, because I'm not an all-knowing being I will make mistakes. Writing tests ensures that at to the lowest degree the worst mistakes are avoided.
  • Is my code testable, before I've written tests for my code information technology might be hard to tell whether it lends itself to be tested. Of course, I need to ask myself at this betoken whether this code should be tested. My advice here if it's non obvious what running the method volition produce or if there is more than i execution path - it should be tested.
  • Being defensive, y'all have a tendency to maintain software over several years. The people doing the maintaining might be you or someone else. One way to communicate what lawmaking is important is to write tests that absolutely should work regardless of what refactorings you lot, or anyone else, attempts to carry out.
  • Documentation, documentation sounds like a good idea at kickoff merely we all know that out of sync documentation is worse than no documentation. For that reason, we tend to not write information technology in the first place, or peradventure feel ok with loftier-level documentation only or rely on tools similar Swagger for example. Believe information technology or not but tests are commonly really practiced documentation. It's one developer to another saying, this is how I retrieve the code should be used. And then for the sake of that time to come maintainer, communicate what your intentions were/are.

What to test

And so what should nosotros exam? Well, my commencement response here is all the paths through the method. The happy path besides as alternate paths.

My 2d response is to understand whether we are testing a part to produce a sure result like one+one equals 2 or whether it's more than a behavior similar - we should have been paid before we can ship the items in the cart.

Demo - let'due south test it

What are we doing? Well, nosotros have talked repeatedly about that Shopping Cart in an e-commerce application so let'due south use that as an example for our demo.

This is clearly a case of behavior testing. We want the Cart items to be shipped to a client providing we got paid. That means nosotros demand to verify that the payment is carried out correctly and we also demand a way to affirm what happens if the payment fails.

We volition demand the post-obit:

  • A CartController , will incorporate logic such every bit trying to get paid for a cart's content. If nosotros are successfully paid then ship the items in the cart to a specified address.
  • Helper services, we demand a few helper services to effigy this out like:
    • ICartService, this should assistance us calculate how much the items in cart costs but too tell us exactly what the content is and then nosotros tin can transport this out to a customer once we have gotten paid.
    • IPaymentService, this should charge a card with a specified sum
    • IShipmentService, this should be able to send the cart content to a specific address

Creating the code

We volition need two different .NET Core projects for this:

  • a webapi project, this should contain our production code and acquit out the business logic every bit stated by the CartController and its helper services.
  • a examination projection, this projection volition comprise all the tests and a reference to the above projection.

The API project

For this projection, this could be either an app using the template mvc, webapp or webapi

Showtime, let'south create a solution. Create a directory like so:

            mkdir <new directory name> cd <new directory proper name>                      

1
2

Thereafter create a new solution like so:

To create our API project we merely need to instantiate information technology like so:

            dotnet new webapi -o api                      

1

and lastly add it to the solution like so:

            dotnet sln add api/api.csproj                      

1

Controllers/CartController.cs

Add together the file CartController.cs under the directory Controllers and give it the following content:

                          using              System;              using              System.Collections.Generic;              using              Organisation.Linq;              using              Organisation.Threading.Tasks;              using              Microsoft.AspNetCore.Mvc;              using              Services;              namespace              api.Controllers              {              [              ApiController              ]              [              Route              (              "[controller]"              )              ]              public              class              CartController              {              individual              readonly              ICartService              _cartService;              private              readonly              IPaymentService              _paymentService;              individual              readonly              IShipmentService              _shipmentService;              public              CartController              (              ICartService              cartService,              IPaymentService              paymentService,              IShipmentService              shipmentService              )              {              _cartService              =              cartService;              _paymentService              =              paymentService;              _shipmentService              =              shipmentService;              }              [              HttpPost              ]              public              cord              CheckOut              (              ICard              card,              IAddressInfo              addressInfo)              {              var              result              =              _paymentService.              Charge              (_cartService.              Full              (              )              ,              bill of fare)              ;              if              (result)              {              _shipmentService.              Ship              (addressInfo,              _cartService.              Items              (              )              )              ;              render              "charged"              ;              }              else              {              render              "not charged"              ;              }              }              }              }                      

1
ii
3
4
v
half dozen
7
viii
9
ten
eleven
12
xiii
fourteen
15
sixteen
17
eighteen
nineteen
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

Ok, our controller is created but it has quite a few dependencies in identify that nosotros need to create namely ICartService, IPaymentService and IShipmentService.

Note how we will non create any concrete implementations of our services at this point. We are more interested in establishing and testing the behavior of our lawmaking. That means that concrete service implementations tin come later.

Services/ICartService.cs

Create the file ICartService.cs under the directory Services and requite it the following content:

                          namespace              Services              {              public              interface              ICartService              {              double              Total              (              )              ;              IEnumerable<CartItem>              Items              (              )              ;              }              }                      

1
2
3
4
v
6
vii
8

This interface is just a representation of a shopping cart and is able to tell united states of america what is in the cart through the method Items() and how to calculate its total value through the method Total().

Services/IPaymentService.cs

Let'due south create the file IPaymentService.cs in the directory Services and give it the following content:

                          namespace              Services              {              public              interface              IPaymentService              {              bool              Accuse              (              double              total,              ICard              carte)              ;              }              }                      

i
two
3
four
5
6
7

Now we have a payment service that is able to take total for the amount to be charged and card which is debit/credit menu that contains all the needed data to be charged.

Services/IShipmentService.cs

For our last service permit's create the file IShipmentService.cs under the directory Services with the following content:

                          using              System;              using              Organisation.Generic;              namespace              Services              {              public              interface              IShipmentService              {              void              Ship              (              IAddressInfo              info,              IEnumerable<CartItem>              items)              ;              }              }                      

1
2
iii
4
5
half-dozen
7
viii
nine
10

This contains a method Send() that volition allow us to ship a cart'due south content to the customer.

Services/Models.cs

Create the file Models.cs in the directory Services with the following content:

                          namespace              Services              {              public              interface              IAddressInfo              {              public              string              Street              {              get              ;              fix              ;              }              public              cord              Address              {              get              ;              set              ;              }              public              string              City              {              become              ;              set              ;              }              public              string              PostalCode              {              become              ;              set              ;              }              public              string              PhoneNumber              {              get              ;              set              ;              }              }              public              interface              ICard              {              public              string              CardNumber              {              become              ;              prepare              ;              }              public              cord              Name              {              get              ;              set              ;              }              public              DateTime              ValidTo              {              become              ;              set              ;              }              }              public              interface              CartItem              {              public              string              ProductId              {              get              ;              set              ;              }              public              int              Quantity              {              get              ;              set              ;              }              public              double              Toll{              get              ;              set              ;              }              }              }                      

1
two
iii
4
5
half-dozen
7
8
9
10
11
12
13
xiv
15
16
17
18
nineteen
twenty
21
22
23
24
25

This contains some supporting interfaces that nosotros need for our services.

Creating a test project

Our test project is interested in testing the behavior of CartController. Showtime off we will need a examination project. There are quite a few examination templates supported in .Internet Core like nunit, xunit and mstest. Nosotros'll become with nunit.

To create our examination project we type:

            dotnet new nunit -o api.exam                      

1

Let's add it to the solution like and so:

            dotnet sln add examination/examination.csproj                      

1

Thereafter add together a reference of the API projection to the test project, so nosotros are able to test the API projection:

            dotnet add together examination/exam.csproj reference api/api.csproj                      

1

Finally, we need to install our mocking library moq, with the following command:

Moq, how it works

Let'southward talk apace most our Mock library moq. The thought is to create a concrete implementation of an interface and control how sure methods on that interface responds when called. This will allow united states of america to essentially test all of the paths through code.

Creating our first Mock

Allow's create our outset Mock with the following code:

                          var              paymentServiceMock              =              new                              Mock                <                IPaymentService                >                            (              )              ;                      

1

The in a higher place is non a concrete implementation but a Mock object. A Mock tin be:

  • Instructed, you tin tell a mock that if a sure method is called and then information technology can answer with a sure response
  • Verified, verification is something you carry out afterwards your production code has been called. Y'all carry this out to verify that a certain method has been called with specific arguments

Instruct our Mock

Now nosotros take a Mock object that we tin instruct. To instruct it we use the method Setup() similar then:

            paymentServiceMock.              Setup              (p              =>              p.              Accuse              (              )              )              .              Returns              (              true              )                      

1

Of course, the to a higher place won't compile, we need to give the Charge() method the arguments it needs. In that location are two ways nosotros can give the Charge() method the arguments information technology needs:

  1. Exact arguments, this is when nosotros requite information technology some physical values similar so:
                          var              card              =              new              Card              (              "owner"              ,              "number"              ,              "CVV number"              )              ;              paymentServiceMock.              Setup              (p              =>              p.              Accuse              (              114              ,card)              )              .              Returns              (              truthful              )                      

ane
2
three

  1. General arguments, hither we can employ the helper It, which will allow us to instruct the method Charge() that any values of a certain data type tin can be passed through:
            paymentServiceMock.              Setup              (p              =>              p.              Charge              (It.                              IsAny                <                double                >                            (              )              ,card)              )              .              Returns              (              truthful              )                      

1

Accessing our implementation

We volition need to pass an implementation of our Mock when we telephone call the actual production code. So how do we do that? There's an Object property on the Mock that represents the concrete implementation. Below we are using only that. Nosotros first construct cardMock and then we pass cardMock.Object to the Charge() method.

                          var              cardMock              =              new                              Mock                <                ICard                >                            (              )              ;              paymentServiceMock.              Setup              (p              =>              p.              Charge              (It.                              IsAny                <                double                >                            (              )              ,cardMock.Object)              )              .              Returns              (              true              )                      

1
two
3

Add unit tests

Permit's rename the default test file we got to CartControllerTest.cs. Adjacent, permit's discuss our approach. We want to:

  • Examination all the execution paths, there are currently two different paths through our CartController depending on whether _paymentService.Accuse() answers with truthful or false
  • Write two tests, we need at to the lowest degree two different tests, one for each execution path
  • Assert, we need to ensure that the correct thing happens. In our case, that ways if we successfully go paid then we should send, then that ways asserting that the shipmentService is being called.

Let'due south write our first exam:

                          // CartControllerTest.cs              [              Test              ]              public              void              ShouldReturnCharged              (              )              {              // arrange              paymentServiceMock.              Setup              (p              =>              p.              Charge              (It.                              IsAny                <                double                >                            (              )              ,              cardMock.Object)              )              .              Returns              (              truthful              )              ;              // act              var              issue              =              controller.              CheckOut              (cardMock.Object,              addressInfoMock.Object)              ;              // assert              shipmentServiceMock.              Verify              (south              =>              s.              Ship              (addressInfoMock.Object,              items.              AsEnumerable              (              )              )              ,              Times.              One time              (              )              )              ;              Affirm.              AreEqual              (              "charged"              ,              result)              ;              }                      

1
2
iii
iv
five
6
vii
8
nine
10
eleven
12
xiii
fourteen
15
sixteen

We take three phases in a higher place.

Conform

Allow'south have a look at the code:

            paymentServiceMock.              Setup              (p              =>              p.              Charge              (It.                              IsAny                <                double                >                            (              )              ,              cardMock.Object)              )              .              Returns              (              truthful              )              ;                      

1

here we are setting things up and saying that if our paymentService.Charge() method is chosen with any value It.IsAny<double>() and with a card object cardMock.Object then we should render true, aka .Returns(true). This means we accept set a happy path and are ready to go to the next stage Act.

Human action

Here nosotros call the actual code:

                          var              result              =              controller.              CheckOut              (cardMock.Object,              addressInfoMock.Object)              ;                      

ane

As we can see above we get the answer assigned to the variable result. This takes us to our next stage, Assert.

Affirm

Let'south accept a look at the code:

            shipmentServiceMock.              Verify              (s              =>              s.              Send              (addressInfoMock.Object,              items.              AsEnumerable              (              )              )              ,              Times.              Once              (              )              )              ;              Assert.              AreEqual              (              "charged"              ,              outcome)              ;                      

i
2
three

Now, at that place are two pieces of assertions that have place here. Get-go, we have a Mock exclamation. We come across that as we are calling the method Verify() that essentially says: I expect the Ship() method to accept been chosen with an addressInfo object and a cartItem listing and that information technology was called only once. That all seems reasonable, our paymentService says information technology was paid, we set information technology up to answer truthful.

Next, we have a more normal-looking assertion namely this code:

            Affirm.AreEqual("charged", issue);                      

ane

It says our issue variable should contain the value charged.

A second test

So far nosotros tested the happy path. As nosotros stated earlier, there are 2 paths through this code. The paymentService could decline our payment and then we shouldn't ship any cart content. Allow's see what the code looks similar for that:

                          [              Test              ]              public              void              ShouldReturnNotCharged              (              )              {              // arrange              paymentServiceMock.              Setup              (p              =>              p.              Accuse              (Information technology.                              IsAny                <                double                >                            (              )              ,              cardMock.Object)              )              .              Returns              (              false              )              ;              // act              var              issue              =              controller.              CheckOut              (cardMock.Object,              addressInfoMock.Object)              ;              // assert              shipmentServiceMock.              Verify              (s              =>              due south.              Ship              (addressInfoMock.Object,              items.              AsEnumerable              (              )              )              ,              Times.              Never              (              )              )              ;              Assert.              AreEqual              (              "not charged"              ,              result)              ;              }                      

1
2
iii
4
5
half-dozen
vii
8
ix
10
11
12
xiii
xiv

To a higher place nosotros run into that we take again the three phases Suit, Act and Assert.

Arrange

This fourth dimension around we are ensuring that our paymentService mock is returning fake, aka payment bounced.

            paymentServiceMock.              Setup              (p              =>              p.              Charge              (It.                              IsAny                <                double                >                            (              )              ,              cardMock.Object)              )              .              Returns              (              false              )              ;                      

i

Deed

This office looks exactly the same:

                          var              result              =              controller.              CheckOut              (cardMock.Object,              addressInfoMock.Object)              ;                      

1

Assert

We are nonetheless testing ii pieces of assertions - beliefs and value assertion:

            shipmentServiceMock.              Verify              (s              =>              southward.              Ship              (addressInfoMock.Object,              items.              AsEnumerable              (              )              )              ,              Times.              Never              (              )              )              ;              Assert.              AreEqual              (              "not charged"              ,              result)              ;                      

ane
2

Looking at the code above nosotros, nonetheless, are asserting that shipmentService is not called Times.Never(). That'southward important to verify as that otherwise would lose us money.

The second assertion just tests that the result variable now says not charged.

Total lawmaking

Let's accept a look at the total code so you lot are able to test this out for yourself:

                          // CartControllerTest.cs              using              System;              using              Services;              using              Moq;              using              NUnit.Framework;              using              api.Controllers;              using              Arrangement.Linq;              using              System.Collections.Generic;              namespace              examination              {              public              class              Tests              {              private              CartController              controller;              private              Mock<IPaymentService>              paymentServiceMock;              private              Mock<ICartService>              cartServiceMock;              private              Mock<IShipmentService>              shipmentServiceMock;              private              Mock<ICard>              cardMock;              individual              Mock<IAddressInfo>              addressInfoMock;              private              List<CartItem>              items;              [              SetUp              ]              public              void              Setup              (              )              {              cartServiceMock              =              new                              Mock                <                ICartService                >                            (              )              ;              paymentServiceMock              =              new                              Mock                <                IPaymentService                >                            (              )              ;              shipmentServiceMock              =              new                              Mock                <                IShipmentService                >                            (              )              ;              // adjust              cardMock              =              new                              Mock                <                ICard                >                            (              )              ;              addressInfoMock              =              new                              Mock                <                IAddressInfo                >                            (              )              ;              //                            var              cartItemMock              =              new                              Mock                <                CartItem                >                            (              )              ;              cartItemMock.              Setup              (item              =>              particular.Cost)              .              Returns              (              10              )              ;              items              =              new                              List                <                CartItem                >                            (              )              {              cartItemMock.Object              }              ;              cartServiceMock.              Setup              (c              =>              c.              Items              (              )              )              .              Returns              (items.              AsEnumerable              (              )              )              ;              controller              =              new              CartController              (cartServiceMock.Object,              paymentServiceMock.Object,              shipmentServiceMock.Object)              ;              }              [              Examination              ]              public              void              ShouldReturnCharged              (              )              {              paymentServiceMock.              Setup              (p              =>              p.              Charge              (It.                              IsAny                <                double                >                            (              )              ,              cardMock.Object)              )              .              Returns              (              truthful              )              ;              // act              var              event              =              controller.              CheckOut              (cardMock.Object,              addressInfoMock.Object)              ;              // assert              // myInterfaceMock.Verify((thousand => m.DoesSomething()), Times.One time());              shipmentServiceMock.              Verify              (southward              =>              due south.              Ship              (addressInfoMock.Object,              items.              AsEnumerable              (              )              )              ,              Times.              Once              (              )              )              ;              Assert.              AreEqual              (              "charged"              ,              issue)              ;              }              [              Test              ]              public              void              ShouldReturnNotCharged              (              )              {              paymentServiceMock.              Setup              (p              =>              p.              Accuse              (It.                              IsAny                <                double                >                            (              )              ,              cardMock.Object)              )              .              Returns              (              false              )              ;              // human activity              var              event              =              controller.              CheckOut              (cardMock.Object,              addressInfoMock.Object)              ;              // assert              shipmentServiceMock.              Verify              (s              =>              due south.              Transport              (addressInfoMock.Object,              items.              AsEnumerable              (              )              )              ,              Times.              Never              (              )              )              ;              Assert.              AreEqual              (              "non charged"              ,              issue)              ;              }              }              }                      

1
2
3
four
5
6
7
8
nine
10
11
12
13
14
15
16
17
18
xix
20
21
22
23
24
25
26
27
28
29
thirty
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
sixty
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

Final thoughts

So nosotros have managed to exam out the two major paths through our lawmaking simply there are more than tests, more than assertions nosotros could be doing. For case, we could ensure that the value of the Cart corresponds to what the customer is actually being charged. As well all know in the existent world things are more complicated. Nosotros might need to update the API lawmaking to consider timeouts or errors being thrown from the Shipment service too as the payment service.

Summary

I've hopefully been able to convey some good reasons for why you lot should test your code. Additionally, I hope y'all think the library moq looks like a good candidate to aid y'all with the more than behavioral aspects of your lawmaking.

Source: https://softchris.github.io/pages/dotnet-moq.html

Posted by: palmerwhinsise1961.blogspot.com

0 Response to "How To Find Out Whether You Are Signed Up For Selective Service"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel