Problem statement

I have a class which:

  1. Is internal in a separate assembly from tests (InternalsVisibleTo is set, so the test project sees the class).
  2. Has no parameter-less constructor.
  3. Has a protected method which I want to mock (only this method, I want to use the others).
internal class ClassToTest {
  public ClassToTest(int x, int y) {
  }
  public void MethodToTest() {
    // ...
    var b = MethodToMock(1);
    // ...
  }
  protected string MethodToMock(int a) {
  }
}

There are several problems to solve here:

  1. How to mock internal class?
  2. How to mock a class with no parameter-less constructor
  3. How to mock only some of the methods in a class?
  4. How to mock protected method?

Solution

How to mock internal class?

The solution I've found in this article. Basically, when the class is internal you should make it visible to the test project by applying assembly attribute InternalsVisibleTo. But Moq is one another assembly that can't see what is inside tested project. So I need to apply another attribute:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
// or in case of signed assemblies
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2," +
  "PublicKey=0024000004800000940000000602000000240000525" +
  "341310004000001000100c547cac37abd99c8db225ef2f6c8a360" +
  "2f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d" +
  "9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b19119" +
  "5b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924c" +
  "ceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92" +
  "484cf7045cc7")]

Now I can mock an internal class from within a test project.

How to mock a class with no parameter-less constructor

The answer lies in the Mock class constructor (and in this StackOverflow answer.)

In case of my contructor I need to pass the parameter to the constructor of Mock class:

var myMock = new Mock<ClassToTest>(
     MockBehavior.Default,
     2 /* 1st parameter of ClassToTest constructor */,
     4 /* 2nd parameter of ClassToTest constructor */);

How to mock only some of the methods in a class?

This is also known as "Partial Mock". This is described in the official QuickStart document of Moq. in the section "Customizing Mock Behavior". What I need is just to add:

myMock.CallBase = true;

How to mock protected method?

One more time QuickStart document comes to the rescue (). Moq doesn't provide intellisense for protected methods. I need to:

// Add using statement
using Moq.Protected;

// Mock the method
myMock.Protected().Setup<string>("MethodToMock",
        ItExpr.IsAny<int>())
        .Returns("myReturnValue");