Method check was called

Using Moq, I have a very strange problem when setting to layout only works if the method I'm setting up is public. I do not know if this is a Moq error, or if I am just mistaken (new to Moq). Here is a test case:

public class TestClass { public string Say() { return Hello(); } internal virtual string Hello() { return ""; } } [TestMethod] public void Say_WhenPublic_CallsHello() { Mock<TestClass> mock = new Mock<TestClass>(); mock.Setup(x => x.Hello()).Returns("Hello World"); string result = mock.Object.Say(); mock.Verify(x => x.Hello(), Times.Exactly(1)); Assert.AreEqual("Hello World", result); } 

What fails with this message:

Say_WhenPublic_CallsHello failed: Moq.MockException: Call failed on layout 1 time: x => x.Hello () in Moq.Mock.ThrowVerifyException (expected IProxyCall, Expression expression, times times) ...

If I make the Hello method public, the test passes. What is the problem?

 public virtual string Hello() { return ""; } 

Thanks in advance!

+22
c # moq mocking
Dec 30 '09 at 13:04
source share
3 answers

The test fails when Hello() is internal, because Moq cannot provide method overrides in this case. This means that the internal implementation of Hello() will be launched, not the layout of the version, as a result of which Verify() will fail.

By the way, what you are doing here does not make sense in the context of unit test. A unit test does not care that Say() calls the internal Hello() method. This is an implementation internal to your assembly, not a code consumption issue.

+18
Dec 30 '09 at 13:14
source share

I don’t know enough about how this works under the covers to give you a technical answer about why this behavior is, but I think I can help with your confusion.

In your example, you call the Say () method, and it returns the expected text. Your expectation should not ensure the implementation of a specific Say () implementation, i.e. Calls the internal Hello () method to return this string. This is why it does not pass validation, and also why the returned string is "", i.e. the actual implementation of Hello () was called.

By providing the public Hello method, this means that it allowed Moq to intercept the call to it and use it instead. Therefore, in this case, the test seems to pass. However, in this case, you really did not do anything, because in your test it says that when Say () is called, the result is "Hello World", when in the acutal fact the result is "".

I rewrote your example to show how I expect Moq to be used (not necessarily final, but hopefully clear.

 public interface IHelloProvider { string Hello(); } public class TestClass { private readonly IHelloProvider _provider; public TestClass(IHelloProvider provider) { _provider = provider; } public string Say() { return _provider.Hello(); } } [TestMethod] public void WhenSayCallsHelloProviderAndReturnsResult() { //Given Mock<IHelloProvider> mock = new Mock<IHelloProvider>(); TestClass concrete = new TestClass(mock.Object); //Expect mock.Setup(x => x.Hello()).Returns("Hello World"); //When string result = concrete.Say(); //Then mock.Verify(x => x.Hello(), Times.Exactly(1)); Assert.AreEqual("Hello World", result); } 

In my example, I introduced an interface for IHelloProvider. You will notice that the implementation of IHelloProvider fails. This is at the core of what we are trying to achieve using a mocking solution.

We are trying to test a class (TestClass), which depends on something external (IHelloProvider). If you use Test Driven Development, you probably haven't written IHelloProvider yet, but know that you will need one at some point. First you want TestClass to work, not get distracted. Or maybe IHelloProvider is using a database or a flat file, or it's hard to configure.

Even if you have a fully working IHelloProvider, you are still trying to test the behavior of TestClass, so using a specific HelloProvider is likely to make your test more prone to failure, for example, if there is a change in behavior from HelloProvider, you do not want to change the tests of each class that uses it, you just want to change the HelloProvider tests.

Returning to the code, we now have the TestClass class, which depends on the IHelloProvider interface, the implementation of which is provided at build time (this is an dependency injection).

The behavior of Say () is that it calls the Hello () method on IHelloProvider.

If you look at the test, we created the actual TestClass object, since we really want to test the code that we wrote. We created the Mock IHelloProvider and said we expect it to call the Hello () method, and when it returns the string "Hello World".

Then we call Say () and check the results as before.

It is important to understand that we are not interested in the behavior of IHelloProvider, and therefore we can mock him to simplify testing. We are interested in the behavior of TestClass, so we created the actual TestClass, not the Mock, so that we can check its actual behavior.

Hope this helps clarify what is happening.

+10
Dec 30 '09 at 13:49
source share

Moq does not do partial bullying and can only trick public virtual methods or interfaces. When you create a Mock, you create a completely new T and delete the entire implementation of any public virtual methods.

My suggestion would be to focus on testing the area of ​​the public surfaces of your objects , and not on their internal elements. Your internal people will get coverage. Just make sure you have a clear idea of ​​what your target class is and not mock it (in most cases).

Partial bullying is only useful when you want to test the functionality of an abstract class with mocking implementations of abstract methods. If you do not, you will most likely not see the big benefits of a partial layout.

If this is not an abstract class, you need to focus more on Modan's approach, which says that you should mock dependencies, not your target class. It all boils down to the rule of not mocking what you are testing .

+6
Jan 04 '10 at 15:57
source share



All Articles