A unit test checks one component’s behavior apart from the rest of an ASP.NET Core application. A self-contained model is straightforward to test; a controller that depends on a data source needs a controlled substitute. Test the behavior most likely to cause trouble, but don’t mistake a passing test for proof that its assertion is right. section 6.0 section 6.3.5 section 6.3.4
For an xUnit test in an ASP.NET Core solution:
- Create a separate test project so tests need not be deployed with the application: `dotnet new xunit -o SimpleApp.Tests --framework net7.0`; add it to the solution and reference the application project. section 6.2
- Put tests in C# classes, with names that identify the component and behavior. Mark each test method `[Fact]`; arrange its inputs, act on the component, then assert the expected result with `Assert`. section 6.3
- Run tests with `dotnet test` or a Visual Studio or Visual Studio Code test runner. In Visual Studio, build the solution if Test Explorer has not discovered the tests. section 6.4 section 6.3.1
Test a model property
Arrange a `Product` with `Price = 100M`, set `Price = 200M`, and assert `Assert.Equal(200M, p.Price)`. Comparing against the old value makes the test fail even though the property works. When a new test fails, inspect its expected value before changing application code. section 6.3 section 6.3.4
To test a controller independently, move its product supply behind an `IDataSource` interface and give the test a fake implementation containing known products. Call the action, read the model from its `ViewResult`, and compare it with the expected products. For custom object comparisons, `Assert.Equal` can accept an `IEqualityComparer<T>`; a small helper can make those comparisons easier to write. section 6.3.5
Test behavior beyond a property
For pagination, configure a Moq `IStoreRepository` with known products, call the controller action, and assert the page model’s counts. For checkout, use a mock order repository: an empty cart or an error added to `ModelState` must prevent `SaveOrder`, while a valid checkout must call it once and redirect. Adding a `ModelState` error simulates a binding problem; directly calling the action does not run model binding. section 7.4.1 section 8.1.4 section 9.3.5
Listing 6.12 Correcting a test in the ProductTests.cs file in the SimpleApp.Tests folder
using SimpleApp.Models;
using Xunit;
namespace SimpleApp.Tests {
public class ProductTests {
[Fact]
public void CanChangeProductName() {
// Arrange
var p = new Product { Name = "Test", Price = 100M };
// Act
p.Name = "New Name";
//Assert
Assert.Equal("New Name", p.Name);
}
[Fact]
public void CanChangeProductPrice() {
// Arrange
var p = new Product { Name = "Test", Price = 100M };
// Act
p.Price = 200M;
//Assert
Assert.Equal(200M, p.Price);
}
}
}
The corrected complete test class shows `[Fact]`, arrange-act-assert comments, and the expected price after the change. section 6.3.4








