8

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?

Caio Cunha
  • 23,326
  • 6
  • 78
  • 74
  • Check this post: http://stackoverflow.com/questions/1458300/moq-how-do-you-test-internal-methods – Blindsniper Jan 04 '14 at 03:24
  • Thx @Blindsniper, but my problem is not about mocking the `internal` method simply. As I said, I did use `InternalsVisibleTo` directive, but for some reason, the test stop succeeding after changing it to internal. – Caio Cunha Jan 04 '14 at 03:28
  • It looks like it should work. You get no exception from Moq about mocking an inaccessible member? Then the `Setup` should work. What happens if you do not set `CallBase = true`? – Jeppe Stig Nielsen Jan 04 '14 at 19:46
  • 1
    Thanks @JeppeStigNielsen. The problem was solved. When I said I used `InternalsVisibleTo`, I didn't know [I should also let it visible to the proxying assembly](http://stackoverflow.com/a/20917943/179138). It's now working. – Caio Cunha Jan 05 '14 at 01:39

1 Answers1

17

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

Adarsh Shah
  • 6,755
  • 2
  • 25
  • 39
  • Perfect! I thought I should only mark it visible to the test assembly, but your explanation enlightened me! It's now clear. Thank you. – Caio Cunha Jan 05 '14 at 01:36