Recursive mocking using Moq

Introduction

When we want to mock a method that’s inside an interface which is inside another interface. This can go tricky.

I’ll have a look at easy way mocking recursively using Moq.

Prerequisite

Moq mocking library ( Nuget package)

Case

There is a class having a dependency of IFoo interface, and IFoo contains IBar interface as a property and IBar have a method, which is what I want to mock.

Let’s think about a class like below.

 public class MoqTest
 {
 private IFoo _foo;

 public MoqTest(IFoo foo)
 {
   this._foo = foo;
 }

 public string Run(string id, string pass)
 {
   var result = _foo.Bar.DoBar(id, pass);

   // do something with result

   return result;
 }

 public string RunSimple()
 {
   var result = _foo.DoFoo();
  
   // do something with result

   return result;
 }

 }

MoqTest class have a dependency of IFoo. IFoo has a Bar class and Bar class have a DoBar method. We want to mock Foo, Bar, and Dobar.

What I need to test is the logic inside Run method of MoqTest class, so I need to mock Foo, Bar and Dobar.

Now, quickly have a look at IFoo and IBar

public interface IFoo
{
  IBar Bar { get; }
  string DoFoo();
}

public interface IBar
{
  string DoBar(string id, string pass);
}

Now Foo class and Bar class looks like below.

public class Foo : IFoo
{
  private IBar _bar;

  public IBar Bar => _bar ?? (_bar = new Bar());

  public string DoFoo()
  {
   return "Foo done";
  }
}

public class Bar : IBar
 {
   public string DoBar(string id, string pass)
   {
     return "Bar done";
   }
}

Find and install Moq Nuget package, if you haven’t installed Moq yet. I’ll skip the explanation about who to use Nuget package. There are so many guides on this already.

Now, let’s test simple one first.

using Moq;

[TestMethod]
public void Test_SimpleMock()
{
  var mockFoo = new Mock<IFoo>();
  var test = new MoqTest.MoqTest(mockFoo.Object);
  var expected = "Foo done";
  var actual = test.RunSimple();
  Assert.AreEqual(expected, actual);
}

This is straightforward mocking with Moq, if you know to use Moq.

See: Moq Quick Start

Next, mock recursively to mock an interface inside an interface.

I initially expected Moq can create recursive mocking when setting up like below.

var mockBar = new Mock<IBar>();
mockFoo.Object.Bar.Object.Setup();

Or, create Bar mock first and Setup mockBar and then create Foo mock, then hopefully Moq understand what I want and provide recursive mocking like below.

 var mockBar = new Mock<IBar>();
 mockBar.Setup();
 var mockFoo = new Mock<IFoo>();

My instinct didn’t work and the correct solution was as below.

[TestMethod]
public void Test_RecursiveMock()
{
 var mockFoo = new Mock<IFoo>() { DefaultValue = DefaultValue.Mock };
 var bar = mockFoo.Object.Bar;

 var barMock = Mock.Get(bar);
 barMock.Setup(a => a.DoBar("id", "pass")).Returns("mocked");

 var test = new MoqTest.MoqTest(mockFoo.Object);
 var expected = "mocked";
 var actual = test.Run("id", "pass");

 Assert.AreEqual(expected, actual);
}

A few noticeable points.

Use DefaultValue.Mock option, which will instantiate all properties and method by default. If not used, only methods defined by Setup will instantiate.

{ DefaultValue = DefaultValue.Mock }

Use Mock.Get() to recursively mock Bar class and then, Setup a method with a return value. I initially expected Moq can create recursive mocking for Bar class when

Actually, recursive mocking using Moq is well explained in Moq Quick Start.

However, if your application, in reality, is complex, mocking can be tricky. For instance, IFoo can be an authentication API or a third-party library.

All test code above can be found on GitHub

Moq is awesome!

2 comments

Leave a comment

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