Styles of Unit Tests

Learning Objectives

Session Outline

Connect - Audit review

Open the AuditManager_Should test class from the Audit kata - the code is in the Audit-Kata repo.

Concepts - Styles and costs

State-Based Style

State-Based Example

[Fact]
public void It_Should_Add_Given_Product_To_The_Order()
{
    var product = new Product("Free Guy");
    var sut = new Order();

    sut.Add(product);

    sut.Products.Should()
        .HaveCount(1)
        .And.Satisfy(item => item.Equals(product));
}

Output-Based Style

Output-Based Example

[Fact]
public void Discount_Of_2_Products_Should_Be_2_Percent()
{
    var product1 = new Product("Kaamelott");
    var product2 = new Product("Free Guy");

    var discount = PriceEngine.CalculateDiscount(product1, product2);
    
    discount.Should().Be(0.02);
}

Communication-Based Style

Refactorings are harder with Communication-based : if you change the interaction you need to change the tests as well.

Communication-Based Example

[Fact]
public void Greet_A_User_Should_Send_An_Email_To_It()
{
    const string email = "john.doe@email.com";
    var emailGatewayMock = new Mock<IEmailGateway>();
    var sut = new Controller(emailGatewayMock.Object);
    
    sut.GreetUser(email);

    emailGatewayMock.Verify(e => e.SendGreetingsEmail(email), Times.Once);
}

The images above are part of the Unit Testing Principles, Practices and Patterns book infographic available here.

Concrete Practice - Refactor to output-based testing

Explain the purpose of the Audit kata.

Ask them to:

Functional code

A step-by-step guide is available here.

Conclusion

Compare the first version of the unit test with the new one.

Which one is the easiest to read and why ?

Resources

Concepts are coming from Vladimir Khorikov’s book : Unit Testing Principles, Practices and Patterns.