AspNetCore.Simple.MsTest.Sdk
4.0.10
dotnet add package AspNetCore.Simple.MsTest.Sdk --version 4.0.10
NuGet\Install-Package AspNetCore.Simple.MsTest.Sdk -Version 4.0.10
<PackageReference Include="AspNetCore.Simple.MsTest.Sdk" Version="4.0.10" />
paket add AspNetCore.Simple.MsTest.Sdk --version 4.0.10
#r "nuget: AspNetCore.Simple.MsTest.Sdk, 4.0.10"
// Install AspNetCore.Simple.MsTest.Sdk as a Cake Addin #addin nuget:?package=AspNetCore.Simple.MsTest.Sdk&version=4.0.10 // Install AspNetCore.Simple.MsTest.Sdk as a Cake Tool #tool nuget:?package=AspNetCore.Simple.MsTest.Sdk&version=4.0.10
AspNetCore.Simple.MsTest.Sdk
Target of this package is to write more efficient clean test against your ASP.Net Core API's. You will save tons of Assert and will be able to write even more faster and better readable test as before. Main reason was to be more focused on the Test-First approach.
Getting started
Prerequisites
Install the package
dotnet add package AspNetCore.Simple.MsTest.Sdk
Samples
Simple object comparisons
[TestMethod]
public void Simple_Object_Comparison()
{
var person1 = new Person("Son", "Goku", 29);
var person2 = new Person("Muten", "Roshi", 63);
Assert.That.ObjectsAreEqual(person1, person2, title: "Persons are not equal");
}
[TestMethod]
public void Simple_Object_Comparison()
{
var firstNumber = 1;
var secondNumber = 2;
Assert.That.ObjectsAreEqual(firstNumber,secondNumber, title: "Persons are not equal");
}
Assert.IsTrue failed.
Persons are not equal
----------------------------------
| MemberPath | person1 | person2 |
----------------------------------
| Name | Son | Muten |
----------------------------------
| FamilyName | Goku | Roshi |
----------------------------------
| Age | 29 | 63 |
----------------------------------
Count: 3
Current result:
{"Name":"Muten","FamilyName":"Roshi","Age":63}
Expected result:
{"Name":"Son","FamilyName":"Goku","Age":29}
Basic concept
// Those assert helper are smart they do following things:
// - Assser the expected call for Sucess -> AssertPostAsync -> Ok AssertPostAsErrorAsync -> NOK
// - It compares the complete reponse structure for equality -> Not only IsSuccessStatusCode, Also deep object
// - You can provide json as string, or like here in the sample a json file which is embedded in the test assembly
// - Why json -> it is that fomat which is used for communication, and you can directly use your payloads in curl,
// postman or anywhere -> if you have c# code -> transform first into json, not nice to handle comparison
// - With this syntax you see directly the route which will be called
// - It is all made for maximize productivity
await Client.AssertPostAsync<AddUserReponse>($"api/v1/users/",
"Users.V1.Payloads.NewUser.json,
"Users.V1.Results.NewUser.json);
Embedded json file or native json string
[TestMethod]
public Task Should_Return_No_Users_If_No_One_Was_Added()
{
return Client.AssertGetAsync<GetAllUsersResponse>("v1/users", "EmptyUserResponse.json");
}
[TestMethod]
public Task Should_Return_No_Users_If_No_One_Was_Added()
{
return Client.AssertGetAsync<GetAllUsersResponse>("v1/users", """{ "Users": [] }""");
}
Assert that GET all Users will returned 401 Unauthorized
[TestMethod]
public Task Should_Not_Return_All_Users_Without_Authentication()
{
return Client.AssertGetAsUnauthorizedAsync("v1/users");
}
Assert that GET a user which not exists returns ProblemDetails
[TestMethod]
public Task Should_Return_Not_Found_Error_If_User_Does_Not_Exits()
{
return Client.AssertGetAsErrorAsync<ProblemDetails>($"v1/users/{1234}", "UserGetByIdErrorResponse.json");
}
Assert that GET all Users is successful and checks that response is empty
[TestMethod]
public Task Should_Return_No_Users_If_No_One_Was_Added()
{
return Client.AssertGetAsync<GetAllUsersResponse>("v1/users", "EmptyUserResponse.json");
}
Create a User and Ignore an Id which maybe is generated by the backend or database
[TestMethod]
public Task Should_Return_Expected_Result_For_Given_Payload_But_Ignore_Id()
{
await Client.AssertPostAsync<AddUserReponse>($"api/v1/users/",
"Users.V1.Payloads.NewUser.json",
"Users.V1.Results.NewUser.json",
differenceFunc: DifferenceFunc);
}
// Difference func can be used to intercept the object comparison in the background
private IEnumerable<Difference> DifferenceFunc(IImmutableList<Difference> differences)
{
foreach (var difference in differences)
{
// Here we ignore the Id property. Real world scenario generated id by database as an example
if (difference.MemberPath == nameof(User.Id))
{
continue;
}
yield return difference;
}
}
Ignore functionality on error response
[TestMethod]
public Task Should_Handle_Error_Response_With_Filter_Func()
{
// 1. Call endpoint which will return an error response
return Client.AssertPostAsErrorAsync<ProblemDetails>("api/tests/v1/errors/not-implemented",
"ErrorResponse.json",
DifferenceFunc);
// 2. Intercept difference detection also for error response
static IEnumerable<Difference> DifferenceFunc(IImmutableList<Difference> differences)
{
foreach (var difference in differences)
{
yield return difference;
}
}
}
Fetch data from an API and do a post order to bring the items in the right order
[TestMethod]
public Task Should_Return_Expected_Result_For_Given_Payload_And_Sorted()
{
return Client.AssertGetAsync<IEnumerable<Person>>($"api/v1/users/",
"Users.V1.Results.AllUsers.json",
filterFunc: FilterFunc);
}
// The filter func can be used to sort or do some custom post filtering
// Sample: You get unsorted results from API so each call will provide
// the users in different order. Why a something like a DB query
// without sort action will not guarantee the order of the results.
// If results does not match the expected results (order as well),
// the test will fail
private IEnumerable<Person> FilterFunc(IEnumerable<Person> arg)
{
return arg.OrderBy(x => x.Id).ToImmutableList();
}
Whole create, get and delete scenario. Looks nice and clean
[TestMethod]
public Task Should_Return_The_User_Which_Was_Added()
{
// 1. Add an user
var addedUserResponse = await Client.AssertPostAsync<AddUserReponse>($"api/v1/users/",
"Users.V1.Payloads.NewUser.json",
"Users.V1.Results.NewUser.json");
// 2. Get the currently added user
await Client.AssertGetAsync<GetAllUserResponse>($"api/v1/users/{addedUserResponse.User.Id}"
"Users.V1.Results.AddedUser.json");
// 3. Delete the alrady added user -> Dependent on your test setup a test-tear down can also contain a cleanup step to remove all the created sources
await Client.AssertDeleteAsync($"api/v1/users/{addedUserResponse.User.Id}"
"Users.V1.Results.Deleteduser.json");
}
Replacements
[TestMethod]
public Task Should_Return_The_User_Which_Was_Added()
{
// 1. Add an user
var addedUserResponse = await Client.AssertPostAsync<AddUserReponse>($"api/v1/users/",
"Users.V1.Payloads.NewUser.json",
"Users.V1.Results.NewUser.json");
// 2. Get the currently added user
await Client.AssertGetAsync<GetUserByIdResponse>($"api/v1/users/{addedUserResponse.User.Id}"
"Users.V1.Results.AddedUser.json",
[("{Id}", addedUserResponse.User.Id)]); // New, will replace in the Users.V1.Results.AddedUser.json the {Id} with the value of addedUserResponse.User.Id
// 3. Delete the alrady added user -> Dependent on your test setup a test-tear down can also contain a cleanup step to remove all the created sources
await Client.AssertDeleteAsync($"api/v1/users/{addedUserResponse.User.Id}"
"Users.V1.Results.Deleteduser.json");
}
Curl for each Asserted
call
How pratical can it be so share call scenarios with your consumers. For that reason you see in the test output the curl command for each asserted call.
-----------------------------------------------------------
Http call as curl
-----------------------------------------------------------
curl \
--location \
--request GET 'https://localhost:5001/api/tests/v1/persons'
-----------------------------------------------------------
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- ConsoleTables (>= 2.6.1)
- Extensions.Pack (>= 5.0.4)
- Microsoft.AspNetCore.Mvc.Testing (>= 8.0.8)
- MSTest.TestFramework (>= 3.5.2)
- System.CodeDom (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
4.0.10 | 3,017 | 9/6/2024 |
4.0.9 | 113 | 9/5/2024 |
4.0.8 | 374 | 9/3/2024 |
4.0.7 | 4,299 | 8/28/2024 |
4.0.6 | 446 | 8/27/2024 |
4.0.5 | 49 | 8/27/2024 |
4.0.4 | 39 | 8/27/2024 |
4.0.3 | 79 | 8/26/2024 |
4.0.2 | 39 | 8/26/2024 |
4.0.1 | 44 | 8/26/2024 |
4.0.0 | 55 | 8/26/2024 |
3.1.1 | 381 | 8/21/2024 |
3.1.0 | 117 | 8/20/2024 |
3.0.4 | 365 | 8/5/2024 |
3.0.3 | 3,651 | 6/20/2024 |
3.0.2 | 564 | 5/26/2024 |
3.0.1 | 1,337 | 4/29/2024 |
3.0.0 | 191 | 4/23/2024 |
2.0.2 | 476 | 4/7/2024 |
2.0.1 | 2,013 | 2/7/2024 |
2.0.0 | 3,688 | 11/28/2023 |
1.1.8 | 1,447 | 10/29/2023 |
1.1.7 | 75 | 10/29/2023 |
1.1.6 | 205 | 10/24/2023 |
1.1.5 | 4,889 | 7/20/2023 |
1.1.4 | 243 | 7/20/2023 |
1.1.3 | 1,734 | 5/31/2023 |
1.1.2 | 92 | 5/29/2023 |
1.1.1 | 751 | 5/20/2023 |
1.1.0 | 93 | 5/20/2023 |
1.0.9 | 1,572 | 4/30/2023 |
1.0.8 | 210 | 4/19/2023 |
1.0.7 | 98 | 4/18/2023 |
1.0.6 | 95 | 4/18/2023 |
1.0.5 | 1,182 | 3/23/2023 |
1.0.4 | 112 | 3/23/2023 |
1.0.3 | 3,738 | 1/1/2023 |
1.0.2 | 120 | 1/1/2023 |
1.0.1 | 108 | 1/1/2023 |
1.0.0 | 141 | 11/24/2022 |
0.7.0 | 2,482 | 11/21/2022 |
0.7.0-alpha.24 | 125 | 11/21/2022 |
0.7.0-alpha.23 | 2,185 | 10/23/2022 |
0.7.0-alpha.22 | 96 | 10/23/2022 |
0.7.0-alpha.20 | 168 | 10/20/2022 |
0.7.0-alpha.18 | 477 | 10/7/2022 |
0.7.0-alpha.16 | 118 | 10/3/2022 |
0.7.0-alpha.14 | 111 | 10/3/2022 |
0.7.0-alpha.13 | 116 | 10/3/2022 |
0.7.0-alpha.12 | 115 | 10/3/2022 |
0.7.0-alpha.11 | 101 | 10/3/2022 |
0.7.0-alpha.8 | 105 | 10/3/2022 |
0.7.0-alpha.7 | 111 | 10/3/2022 |
0.6.1 | 98 | 10/1/2022 |
0.6.0 | 77 | 10/1/2022 |
0.5.1 | 1,157 | 9/4/2022 |
0.5.0 | 84 | 9/4/2022 |
0.4.0 | 89 | 9/3/2022 |
0.3.1 | 117 | 8/24/2022 |
0.3.0 | 226 | 8/4/2022 |
0.2.0 | 203 | 7/25/2022 |
0.2.0-alpha.89 | 229 | 7/8/2022 |
0.2.0-alpha.87 | 121 | 7/8/2022 |
0.2.0-alpha.85 | 222 | 7/4/2022 |
0.2.0-alpha.83 | 177 | 6/30/2022 |
0.2.0-alpha.82 | 153 | 6/21/2022 |
0.2.0-alpha.81 | 265 | 6/19/2022 |
0.2.0-alpha.79 | 121 | 6/19/2022 |
0.2.0-alpha.77 | 235 | 5/25/2022 |
0.2.0-alpha.71 | 445 | 4/28/2022 |
0.2.0-alpha.70 | 304 | 3/11/2022 |
0.2.0-alpha.69 | 127 | 3/11/2022 |
0.2.0-alpha.68 | 976 | 7/2/2021 |
0.2.0-alpha.67 | 2,137 | 5/17/2021 |
0.2.0-alpha.66 | 700 | 4/26/2021 |
0.2.0-alpha.63 | 178 | 4/25/2021 |
0.2.0-alpha.54 | 316 | 4/22/2021 |
0.2.0-alpha.53 | 160 | 4/22/2021 |
0.2.0-alpha.51 | 186 | 4/20/2021 |
0.2.0-alpha.49 | 251 | 4/18/2021 |
0.2.0-alpha.48 | 203 | 4/18/2021 |
0.2.0-alpha.47 | 163 | 4/18/2021 |
0.2.0-alpha.46 | 152 | 4/17/2021 |
0.2.0-alpha.45 | 157 | 4/17/2021 |
0.2.0-alpha.44 | 159 | 4/17/2021 |
0.2.0-alpha.43 | 168 | 4/17/2021 |
0.1.0-alpha.39 | 166 | 4/17/2021 |
0.1.0-alpha.37 | 181 | 4/17/2021 |
0.1.0-alpha.35 | 179 | 4/17/2021 |
0.1.0-alpha.34 | 182 | 4/17/2021 |
0.1.0-alpha.31 | 174 | 4/16/2021 |
0.1.0-alpha.30 | 188 | 4/14/2021 |
0.1.0-alpha.29 | 157 | 4/14/2021 |
0.1.0-alpha.28 | 241 | 4/10/2021 |
0.1.0-alpha.20 | 167 | 4/9/2021 |
0.1.0-alpha.18 | 174 | 4/9/2021 |
0.1.0-alpha.17 | 193 | 4/9/2021 |
0.1.0-alpha.16 | 197 | 4/9/2021 |
0.1.0-alpha.14 | 178 | 4/9/2021 |
0.1.0-alpha.13 | 165 | 4/8/2021 |
0.1.0-alpha.12 | 353 | 4/5/2021 |
Remove ObjectComparer package to compare objects. Comparison is now done by json. Add new difference func to all error assert helpers.