Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial mocking a class internal method with Moq

I have a class that contains a public method, that relies on a internal method in order to properly return its value.

Let's consider the following class and test file:

public class ClassUnderTest
{
    public string NotMockedPublicMethod()
    {
        return MockedMethod();
    }

    virtual public string MockedMethod()
    {
        return "original";
    }
}

The following test case would work:

var mock = new Mock<ClassUnderTest> { CallBase = true };
mock.Setup(m => m.MockedMethod()).Returns("mocked");

Assert.AreEqual("mocked", mock.Object.NotMockedPublicMethod());

But let's say this MockedMethod() of mine has no utility externally. The problem is that marking this method as internal (even using InternalsVisibleTo() properly):

virtual internal string MockedMethod()

will make the exactly same test fails with the message Assert.AreEqual failed. Expected:<mocked>. Actual:<original>.

Is this a Moq bug or some limitation?

like image 962
Caio Cunha Avatar asked Jan 04 '14 03:01

Caio Cunha


People also ask

What can be mocked with Moq?

You can use Moq to create mock objects that simulate or mimic a real object. Moq can be used to mock both classes and interfaces. However, there are a few limitations you should be aware of. The classes to be mocked can't be static or sealed, and the method being mocked should be marked as virtual.

What is partial mocking?

Partial mocks allow you to mock some of the methods of a class while keeping the rest intact. Thus, you keep your original object, not a mock object, and you are still able to write your test methods in isolation. Partial mocking can be performed on both static and instance calls.

How do you mock the method of the same class?

Mocking is done when you invoke methods of a class that has external communication like database calls or rest calls. Through mocking you can explicitly define the return value of methods without actually executing the steps of the method.

What is CallBase in Moq?

CallBase , when initialized during a mock construction, is used to specify whether the base class virtual implementation will be invoked for mocked dependencies if no setup is matched. The default value is false . This is useful when mocking HTML/web controls of the System.


1 Answers

It is not a bug or limitation. Your test is failing after making the method internal (even after adding InternalsVisibleTo) because it is not calling the mocked method but is calling the actual method.

You need to add InternalsVisibleTo for DynamicProxyGenAssembly2 as well as per the below Url.

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

http://www.blackwasp.co.uk/MoqInternals.aspx

The Url doesn't provide proper explanation but here it is:

Moq uses Castle Project's DynamicProxy to generate proxies on the fly at run-time so that members of an object can be intercepted without modifying the code of the class. That's how Moq returns a value specified in "Setup().Returns" (String "mocked" in your case)

Dynamic Proxy Url: http://www.castleproject.org/projects/dynamicproxy/

I looked at the source code (see url below) for DynamicProxy and I see that it uses "DynamicProxyGenAssembly2" as the assembly name for the assembly generated and that is why you need to add InternalsVisibleTo for DynamicProxyGenAssembly2 as well.

public static readonly String DEFAULT_ASSEMBLY_NAME = "DynamicProxyGenAssembly2";

https://github.com/castleproject/Castle.DynamicProxy-READONLY/blob/ed8663b23a54bed641e5f97e39a6bc16fe0d976f/src/Castle.DynamicProxy/ModuleScope.cs

like image 118
Adarsh Shah Avatar answered Sep 24 '22 13:09

Adarsh Shah