|
| 1 | +# Packages |
| 2 | + |
| 3 | +In this section we will learn the most important parts of arranging and asserting our web application components. Of course, as a main building block of the ASP.NET Core MVC framework, we will start with controllers. |
| 4 | + |
| 5 | +Before we begin, let's make a step backwards. Remember the **"project.json"** and the referenced **"MyTested.AspNetCore.Mvc"** dependency? Good! The My Tested ASP.NET Core MVC framework consists of many packages. Here are the most important ones: |
| 6 | + |
| 7 | + - **"MyTested.AspNetCore.Mvc.Core"** - Contains setup and assertion methods for MVC core features - controllers, models and routes |
| 8 | + - **"MyTested.AspNetCore.Mvc.DataAnnotations"** - Contains setup and assertion methods for data annotation validations and model state |
| 9 | + - **"MyTested.AspNetCore.Mvc.ViewFeatures"** - Contains setup and assertion methods for view action results, view data, view components and more |
| 10 | + - **"MyTested.AspNetCore.Mvc"** - Contains assertion methods for the full MVC framework |
| 11 | + |
| 12 | +The packages above reflect the features in the ASP.NET Core packages - "**Microsoft.AspNetCore.Mvc.Core"**, "**Microsoft.AspNetCore.Mvc.DataAnnotations"**, "**Microsoft.AspNetCore.Mvc.ViewFeatures"** and "**Microsoft.AspNetCore.Mvc"**. |
| 13 | + |
| 14 | +These so called "main" packages can be separated further to **"MyTested.AspNetCore.Mvc.Controllers"**, **"MyTested.AspNetCore.Mvc.Routing"**, **"MyTested.AspNetCore.Mvc.ViewActionResults"**, **"MyTested.AspNetCore.Mvc.ViewComponents"** and more. Helper packages for testing non-MVC related features like **"MyTested.AspNetCore.Mvc.EntityFrameworkCore"** and **"MyTested.AspNetCore.Mvc.Authentication"** are also available. |
| 15 | + |
| 16 | +Additionally, these two packages are also available: |
| 17 | + |
| 18 | + - **"MyTested.AspNetCore.Mvc.Universe"** - Combines all available binaries and the whole fluent API into one single package. Use it, if you do not want to include specific smaller packages and want to have every feature available. |
| 19 | + - **"MyTested.AspNetCore.Mvc.Lite"** - Completely **FREE** and **UNLIMITED** version of the library. It should not be used in combination with any other package. Includes ""*Controllers"**, `ViewActionResults"** and `ViewComponents"**. |
| 20 | + |
| 21 | +Full list and descriptions of all available packages can be found [HERE](/guide/packages.html). All of them except the **"Lite"** one require a license code in order to be used without limitations. If a license code is not provided, a maximum of 100 assertions per test project is allowed. More information about the licensing can be found [HERE](/guide/licensing.html). |
| 22 | + |
| 23 | +Now, let's get back to the testing. Go to the **"project.json"** file and replace the **"MyTested.AspNetCore.Mvc"** dependency with **"MyTested.AspNetCore.Mvc.Controllers"**. We will start using the small and specific packages for now and then we will switch to the **"Universe"** one later in the tutorial. |
| 24 | + |
| 25 | +Your **"project.json"** dependencies should look like this: |
| 26 | + |
| 27 | +```json |
| 28 | +"dependencies": { |
| 29 | + "dotnet-test-xunit": "2.2.0-*", |
| 30 | + "xunit": "2.2.0-*", |
| 31 | + "MyTested.AspNetCore.Mvc.Controllers": "1.0.0", |
| 32 | + "MusicStore": "*" |
| 33 | +}, |
| 34 | +``` |
| 35 | + |
| 36 | +If you try to build the solution, you will receive an error stating that **"MyMvc"** does not exist. |
| 37 | + |
| 38 | +<img src="/images/tutorial/mymvcdoesnotexist.jpg" alt="MyMvc no longer exists" /> |
| 39 | + |
| 40 | +The **"MyMvc"** class is only available in the **"MyTested.AspNetCore.Mvc"** package and combines all the different test types into a single starting point. To fix our test, we have to use the **"MyController"** class: |
| 41 | + |
| 42 | +```c# |
| 43 | +[Fact] |
| 44 | +public void AddressAndPayment_ShouldReturn_DefaultView() |
| 45 | + => MyController<CheckoutController> |
| 46 | + .Instance() |
| 47 | + .Calling(c => c.AddressAndPayment()) |
| 48 | + .ShouldReturn() |
| 49 | + .View(); |
| 50 | +``` |
| 51 | + |
| 52 | +Unfortunately, it still does not compile because the **"Controllers"** package contains assertions methods for the [ControllerBase](https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs) class which does not include view features and action results. |
| 53 | + |
| 54 | +You can see this by examining the intellisense of the test result: |
| 55 | + |
| 56 | +<img src="/images/tutorial/coreintellisense.jpg" alt="Controllers package intellisense" /> |
| 57 | + |
| 58 | +We will now try the core action results before returning back to the view features. Comment the first test for now (so that the project will compile with the currently added dependencies) and add a new class named **"ManageControllerTest"** in the **"Controllers"** folder. We will test the asynchronous **"RemoveLogin"** action in the **"ManageController"**. If you examine it, you will notice that it returns **"RedirectToAction"**, if no user is authenticated. |
| 59 | + |
| 60 | +Add the necessary usings and write the following test into the **"ManageControllerTest"** class: |
| 61 | + |
| 62 | +```c# |
| 63 | +[Fact] |
| 64 | +public void RemoveLogin_ShouldReturn_RedirectToAction_WithNoUser() |
| 65 | + => MyController<ManageController> |
| 66 | + .Instance() |
| 67 | + .Calling(c => c.RemoveLogin(null, null)) |
| 68 | + .ShouldReturn() |
| 69 | + .Redirect(); |
| 70 | +``` |
| 71 | + |
| 72 | +Run the test and it should pass correctly. As you can see My Tested ASP.NET Core MVC tests asynchronous actions flawlessly. If you do not like the null values, you may use the built-in helper class **"With"** to specify that there are no action arguments in this test: |
| 73 | + |
| 74 | +```c# |
| 75 | +.Calling(c => c.RemoveLogin(With.No<string>(), With.No<string>())) |
| 76 | +``` |
| 77 | + |
| 78 | +As a bonus, let's assert some details of the redirect action result. We can see it redirects to the **"ManageLogins"** action with some **"ManageMessageId"** route value so we better test them: |
| 79 | + |
| 80 | +```c# |
| 81 | +[Fact] |
| 82 | +public void RemoveLogin_ShouldReturn_RedirectToAction_WithNoUser() |
| 83 | + => MyController<ManageController> |
| 84 | + .Instance() |
| 85 | + .Calling(c => c.RemoveLogin( |
| 86 | + With.No<string>(), |
| 87 | + With.No<string>())) |
| 88 | + .ShouldReturn() |
| 89 | + .Redirect() |
| 90 | + .ToAction(nameof(ManageController.ManageLogins)) |
| 91 | + .ContainingRouteValues(new { Message = ManageController.ManageMessageId.Error }); |
| 92 | +``` |
| 93 | + |
| 94 | +Now we can sleep peacefully! :) |
| 95 | + |
| 96 | +OK, back to that commented test. We cannot test views with our current dependencies. Go to the **"project.json"** and add **"MyTested.AspNetCore.Mvc.ViewActionResults"** ас а dependency: |
| 97 | + |
| 98 | +```json |
| 99 | +"dependencies": { |
| 100 | + "dotnet-test-xunit": "2.2.0-*", |
| 101 | + "xunit": "2.2.0-*", |
| 102 | + "MyTested.AspNetCore.Mvc.Controllers": "1.0.0", |
| 103 | + "MyTested.AspNetCore.Mvc.ViewActionResults": "1.0.0", |
| 104 | + "MusicStore": "*" |
| 105 | +}, |
| 106 | +``` |
| 107 | + |
| 108 | +This package adds all action results from the [Controller](https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Controller.cs) class from the [ViewFeatures](https://github.com/aspnet/Mvc/tree/dev/src/Microsoft.AspNetCore.Mvc.ViewFeatures) MVC package. Go back to the **"CheckoutControllerTest"** class and uncomment the view test. It should compile and pass successfully now. |
| 109 | + |
| 110 | +In this section we learned how we can use only these parts from My Tested ASP.NET Core MVC that we actually need in our testing project. As you can see each small package dependency adds additional extension methods to the fluent API. We will add more and more packages in the next sections so that you can get familiar with them. Next - [Debugging Failed Tests](/tutorial/debugging.html)! |
0 commit comments