C#

Lesson 10

Unit tests with arrange act assert

Structure tests so setup, behavior, and assertions are separate enough for reviewers to see the contract under test.

Good Code

tests/ReviewServiceTests.cs
[Fact]
public async Task FindAsyncReturnsNullWhenReviewIsMissing()
{
    var repository = new FakeReviewRepository();
    var service = new ReviewService(repository);

    // One act step makes the behavior under test easy to see.
    ReviewDto? result = await service.FindAsync(Guid.NewGuid(), CancellationToken.None);

    Assert.Null(result);
}

Bad Code

tests/ReviewServiceTests.cs
[Fact]
public async Task TestReviewService()
{
    var service = new ReviewService(new FakeReviewRepository());
    await service.FindAsync(Guid.NewGuid(), CancellationToken.None);
    await service.FindAsync(Guid.NewGuid(), CancellationToken.None);

    // No assertion means the test only proves the calls did not throw.
}

Review Notes

What to review

Good Code

The good version names the missing-review behavior, performs one action, and asserts the null result.

Bad Code

The bad version has a vague test name, calls the method twice, and contains no assertion. It can pass while the method returns the wrong value.

Takeaways

  • A C# test should name the behavior, create only the data it needs, execute one action, and assert the observable result.