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() {
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.