Unit Test Lazy Loaded Properties

I needed to figure out a way to unit test some code that makes use of Lazy to instanciate its dependencies. I think Lazy sucks but it has its place and I’ve seen first hand massive performance gains in monolithic applications when implemented correctly.

Constructor Injection

To unit test a method that uses a property that is instantiated with Lazy in C#, you can use the following steps:

  1. Create a mock of the Lazy property. Moq is my go to although the recent SponsorLink drama may change that.
  2. Set the mock to return a specific value. This will allow you to test the behavior of the method under different conditions.
  3. Call the method under test.
  4. Verify that the method behaves as expected. You can do this by asserting the values of any output parameters or the state of any external objects.

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using Moq;

public class SweetClass
{
private readonly Lazy<FooService> _fooService;

public SweetClass()
{
_fooService = new Lazy<FooService>(() => new FooService());
}

public void DoWork()
{
// Does magical work with _fooService.
}
}

public class SweetClassTests
{
[Fact]
public void DoWork_GivenX_ShouldY()
{
// Arrange
var fooServiceMock = new Mock<FooService>();
var classUnderTest = new SweetClass { _fooService = new Lazy<FooService>(() => fooServiceMock.Object) };

// Act
classUnderTest.DoWork();

// Assert
fooServiceMock.Verify(x => x.FooServiceMethod());
}
}

In this example, I mocked the FooService property. This allows us to control the behavior of the DoWork() method without having to create a real instance of the FooService class.

Here I used the Verify() method to assert that the FooServiceMethod() method on the FooService mock was called. This means that the DoWork() method under test behaved as expected.

Property Injection

If the constructor is not used to instantiate the Lazy property, you can still unit test the method that uses it by following these steps:

  1. Create a new instance of the class that contains the Lazy property.
  2. Set the Lazy property to a mock of the FooService class.
  3. Call the method under test.
  4. Verify that the method behaves as expected.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using Moq;

public class SweetClass
{
public Lazy<FooService> FooServiceQuery { get; set; }

public void DoWork()
{
// Does magical work with FooServiceQuery.
}
}

public class SweetClassTests
{
[Fact]
public void DoWork_GivenX_ShouldY()
{
// Arrange
var fooServiceMock = new Mock<FooService>();
var classUnderTest = new SweetClass();
classUnderTest.FooServiceQuery = new Lazy<FooService>(() => fooServiceMock.Object);

// Act
classUnderTest.DoWork();

// Assert
fooServiceMock.Verify(x => x.FooServiceMethod());
}
}

In this example, I created a new instance of the SweetClass class and setting the FooServiceQuery property to a mock of the FooService class. This allows control over the behavior of the DoWork() method without having to create a real instance of the FooService class.

Then Verify() is used again the same as the constructor injection example.

Sweetbix.