Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock one method on a class instead of the whole class using Moq?

I have a class

public interface IMyInterface 
{
    string MethodA();
    void MethodB();
}

public class MyClass : IMyInterface
{
    public string MethodA()
    {
        // Do something important
    }

    public void MethodB()
    {
        string value = MethodA();
        // Do something important
    }
}

I want to unit test MethodB, but I'm having trouble thinking about how I can Mock MethodA while still calling into MethodB using Moq. Moq mocks the interface, not the class, so I can't just call mock.Object.MethodB(), right?

Is this possible? If so, how?

like image 609
Kyle Trauberman Avatar asked Jul 28 '12 00:07

Kyle Trauberman


People also ask

How do you mock a method in Moq?

First, we instantiate the FakeDbArticleMock class and indicate which setup we want to use for this test. Then, it is necessary to instantiate the repository we want to test and inject the mock instance into it. Finally, we call the method we are testing and assert the results.

How do you mock the method of the same class?

We can mock runInGround(String location) method inside the PersonTest class as shown below. Instead of using mock(class) here we need to use Mockito. spy() to mock the same class we are testing.

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.

How do I mock a class without an interface?

Simply mark any method you need to fake as virtual (and not private). Then you will be able to create a fake that can override the method. Save this answer.


2 Answers

I don't think it is possible. Even it is possible I'd prefer not to do that.

You are testing behavior of MyClass, the fact that it happen to implement IMyInterface is somewhat unrelated to testing behavior of MethodA and MethodB. You can have separate test that makes sure that class implements interfaces that you expect it to implement if necessary. Testing of MyClass.MethodB should be done on instance of MyClass, not on semi-mocked object.

If you think that behavior of MethodA is dependency you may try actually extract it explicitly from the class. It will allow to test both MethodA (which will simply delegate to the dependency) and MethodB (which will use the dependency and do more).

like image 171
Alexei Levenkov Avatar answered Sep 24 '22 15:09

Alexei Levenkov


Mock dependencies you cannot instanciate easily (or all).
MyClass is class under test, so should not be mocked (you don't want to test mocked values).
But, if you have some MyClass.Foo property that is class Foo which implements IFoo interface and MethodA uses this Foo property, then you can mock it to break dependency.

like image 41
Adronius Avatar answered Sep 23 '22 15:09

Adronius