How to unit test a method that has void as return type

How do I test a method that returns void? For example a method like this.

public void Process(int leadId)
{
    decimal price = _calculator.CalculateNormalLead(leadId);

    Lead lead = new Lead(leadId, price);

    _leadRepository.Save(lead);
}

How to test what the state of the lead object is? This is a question that comes up a lot of the time. It has many different answers. Some options:

  • Return a type anyway, even though you don’t use it. Or expose a property with the result. This are design changes that are only neccesary for testing. I’m sure that’s not what we want.
  • Check what the method changed, like records in the database. That’s a slow integration test.
  • Split the methods so that one portion of it returns something, and the second method just takes the result and uses it. This way however, you’ll have to make two calls to your class, which I think is even worse than the previous two options!
  • Expose internals by using the InternalsVisibleTo attribute. But now you have to make changes to the design of your class again, making private methods or properties internal.
  • Another option is to accept you can’t test everything. What you can however check is
    • Check if it throws exceptions
    • Check if it changes mutable objects you pass in as parameters
    • Do interaction based testing. Either write mocks or use a mocking framework to verify if calls were made to another method.

This last thing is something we can really use. Now this might not always work, but in our case it’s very usable. Imagine we have a repository that in production kind of works like this.

public class LeadRepository : ILeadRepository
{
    public void Save(Lead lead)
    {
        throw new NotImplementedException("Sorry, this is for an integration test.");
    }
}

Now I said kind of, because I don’t want to bother you with a lot of database and query stuff. But our lead enters this class and we’d really like to have this one! This repository implements an interface and the class is injected into the Invoicing class, where our Process method is. For the complete example, check the solution. But for now, check out this FakeRepository I created to use during testing.

public class FakeRepository : ILeadRepository
{
    public Lead CreatedLead { get; private set; }

    public void Save(Lead lead)
    {
        CreatedLead = lead;
    }
}

The only thing this repository does, is put the lead it receives into a property of the FakeRepository class. Remember that the repository in production does not have this property, so normally it’s never exposed.

Now we can write a test that injects our own fake objects and when asserting, we use the property of our FakeRepository to check the state of our lead.

[TestMethod]
public void Does_MapPropertiesCorrectly_When_CalculatingALead()
{
    // Arrange
    int leadId = 1;
    decimal leadPrice = 0.5m;
    FakeRepository fakeRepository = new FakeRepository();
    FakeCalculator calculator = new FakeCalculator(leadPrice);

    // Act
    Invoicing invoicing = new Invoicing(calculator, fakeRepository);
      invoicing.Process(leadId);

    // Assert
    Lead result = fakeRepository.CreatedLead;
    Assert.AreEqual(leadId, result.LeadId);
    Assert.AreEqual(leadPrice, result.Price);
}

See how easy it sometimes is? Download the complete solution here.

You may also like...

3 Responses

  1. Ramon Smits says:

    Why not make use of inheritence?

    I usually just inherit the class do that is has access to protected stuff. This new class is then an internal subclass in my unittest.

    You are using interface so your imlementation methods should be marked virtual which they currently are not. 🙂

  2. Ramon Smits says:

    2nd, why not just create a mock? Then you also can validate that the repository save is actually called.

  3. Dennis van der Stelt says:

    lol, are you going to comment everything!? 😉
    I’m making a series of posts with examples like these.
    About the virtual methods, you’re right. I forgot.

    And about the mock, I’m doing state-based testing here. I know that when writing mocks like these yourself, you can also mark a boolean that some method has been accessed. A mocking framework is even better yet, but I’m trying to keep things as easy as possible. But I’ll add an example with a mocking framework in it as well. The original idea though, started with someone asking me about how to have mocks and inject those with Unity. So I thought, let’s write some posts on it.

Click on a tab to select how you'd like to leave your comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.