Banging My Head Against the Wall

What I wish I knew before I started…

How to mock lazy initialization of objects in C# unit tests using Moq


I was unable to find it clearly documented how to use Moq with objects that are to be lazy initialized, so below are the steps I took to do so.

Here is my class under test:

public class MyClass
{
  [Dependency]
  public Lazy<IWorkflowService> WorkflowService { get; set; }

  [Dependency]
  public Lazy<ISession> Session { get; set; }

  public string MyPublicMethod()
  {
    var someValue = this.WorkflowService.Value.GetSomeValue(this.Session.Value.SessionId);

    //Do something with someValue...
    return someValue;
  }
}

Notice that the GetSomeValue method requires the SessionId off of the Session object.

I now needed to write a unit test for MyPublicMethod().  The question I had was how to actually use Moq with the Session and WorkflowService instances.  Normally, I would just be able to do this in my test:

var mockSession = new Mock<ISession>();
var mockWorkfowService = new Mock<IWorkflowService>(); 

var myClass = new MyClass(); 
myClass.Session = mockSession.Object;
myClass.WorkflowService = mockWorkfowService.Object; 
//Method under test
var actual = myClass.MyPublicMethod();

But when I run the test, I received this error:

System.NullReferenceException: Object reference not set to an instance of an object.

The lazy initialization meant I needed to take another approach.  I read the MSDN Lazy Initialization  documentation and noticed there is a Lazy class constructor that allows you to specify a Func that should be used to return an instance of the object.  I decided to take advantage of this in my test case and return the mock instances that I had already created:

var mockSession = new Mock<ISession>();
var mockWorkfowService = new Mock<IWorkflowService>();

var myClass = new MyClass();

//Make use of the Lazy<T>(Func<T>()) constructor 
//to return the mock instances
myClass.Session = new Lazy<ISession>( () => mockSession.Object);
myClass.WorkflowService = 
    new Lazy<IWorkflowService>( () => mockWorkfowService.Object); 

//Method under test
var actual = myClass.MyPublicMethod();

Re-ran the test and it passed!

 

,

3 responses to “How to mock lazy initialization of objects in C# unit tests using Moq”

Leave a comment