After this lesson, you will be able to: Write unit tests in C# with xUnit, mock dependencies with Moq, and assert fluently with FluentAssertions.
Testing in C# is mature: xUnit is the modern default, Moq + NSubstitute handle mocking, FluentAssertions reads like English. Real projects always have these.
Most popular .NET test framework. Run with `dotnet test`.
// Create test project: dotnet new xunit -o myapp.Tests// Add reference: dotnet add reference ../myapp/myapp.csprojusing Xunit;public class CalculatorTests {[Fact]public void Add_TwoPositives_ReturnsSum() {var calc = new Calculator();var result = calc.Add(2, 3);Assert.Equal(5, result);}[Theory][InlineData(2, 3, 5)][InlineData(0, 0, 0)][InlineData(-1, 1, 0)]public void Add_VariousInputs_ReturnsExpected(int a, int b, int expected) {var calc = new Calculator();Assert.Equal(expected, calc.Add(a, b));}[Fact]public void Divide_ByZero_Throws() {var calc = new Calculator();Assert.Throws<DivideByZeroException>(() => calc.Divide(1, 0));}}
Isolate the unit under test by faking its dependencies.
using Moq;using Xunit;public interface IEmailService {Task SendAsync(string to, string subject);}public class UserService {private readonly IEmailService _email;public UserService(IEmailService email) { _email = email; }public async Task RegisterAsync(string email) {// ... save userawait _email.SendAsync(email, "Welcome!");}}public class UserServiceTests {[Fact]public async Task RegisterAsync_SendsWelcomeEmail() {var mockEmail = new Mock<IEmailService>();var service = new UserService(mockEmail.Object);mockEmail.Verify(e =>Times.Once);}}
Reads like English; better error messages.
using FluentAssertions;// Plain AssertAssert.Equal(5, result);// FluentAssertionsresult.Should().Be(5);result.Should().BeGreaterThan(0).And.BeLessThan(10);var users = new[] { "Alex", "Sam" };users.Should().HaveCount(2);users.Should().Contain("Alex");users.Should().BeInAscendingOrder();Action act = () => calc.Divide(1, 0);act.Should().Throw<DivideByZeroException>();// On error:// Plain: Assert.Equal() Failure// Fluent: Expected result to be 5, but found 4.
Mocking everything → tests pass but don't actually test the system. Asserting on private fields via reflection (extremely brittle). Single-test files with 50 tests (split by behavior). Naming tests `Test1`, `Test2` (use `Method_Scenario_ExpectedResult`).
Sign in and purchase access to unlock this lesson.