Question

So I have the following class:

public class MyClass {
  internal void A() {
    foreach(Thing thing in ThingArray)
      B(thing);
  }

  virtual internal void B(Thing thing)
  {
    //  do some stuff
  }
}

And then I have the following test:

...
var testObject = new Mock<MyClass>(parameters);
testObject.Setup(t => t.B(It.IsAny<Thing>()));

test.Object.A();

test.Verify(t => t.B(It.IsAny<Thing>()), Times.Exactly(2));

And the verify is failing. I've checked, and the code is calling the real B() method as opposed to a mocked B() method.

I've got a lot of code running where Moq works perfectly, and I've been coding long enough to realize that I must be doing something wrong here, but for the life of me I can't see it. I've been proceeding under the assumption that since I'm calling test.Object.A(), the calls to B() are not going through the Mock, but that really doesn't make any sense to me since a call from any other object would work the same...

So why on earth isn't the mocked setup being executed?

Edit: Yes, I have the internals visible to the test project. I meant to put that into the original post, since I knew someone would mention it.

As to the real code, it is unfortunately VERY proprietary, so I can't post it. I'll see if I can adjust the code tomorrow to make it actually compile.

Was it helpful?

Solution

I'm not sure if Gamlor's answer works. It seems that if you want to perform a setup on a method where you want to verify that Class1.MethodA calls Class1.MethodB, MethodB (which is the one you would do the setup on) has to be public (regardless of InternalsVisibleTo). I wrote a simple test under a similar situation and found that once I made my MethodB public, Moq started working. I would bet if you made your method B public, it would work.

I assume this is a Castle or Moq bug but I don't know for sure. Hopefully somebody will chime in.

I know making MethodB public is not a good choice. But that is what I know about the situation...

OTHER TIPS

The object your Mock has to meet this criterias in order to make a successfully mock a method:

  • It has to be an interface
  • Or the method you want to mock has to be a virtual method and public.

Now you can also mock virtual-internal method, but in order to allow that you have to give Moq access to your internals. This you can do with:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

This make the internal accessible to the code-generator of Moq.

So in order to mock your MyClass.A call you have to do this:

  1. Make you method A virtual.
  2. And make your method public or allow access with

    [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
    

Or as said, make an interface which represents the API of MyClass.

Moq doesn't wrap the existing code, but instead creates an empty mock.

That means that calling testObject.Object.A() doesn't execute your original code, so B is never called.

If you pretend your mocking an interface then this makes sense because interfaces don't have code, so neither would the mock.

Try creating the mock like this (I didn't try it so I don't know if it works):

var testObject= new Mock<MyClass> { CallBase = true };
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top