Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit test to verify that a base class method is called

I have a base class:

public abstract class MyBaseClass
{
    protected virtual void Method1()
    {    
    }
} 

and a derived class:

public class MyDerivedClass : MyBaseClass
{
    public void Method2()
    {
        base.Method1();
    }
}

I want to write a unit test for Method2 to verify that it calls Method1 on the base class. I'm using Moq as my mocking library. Is this possible?

I came across a related SO link:

Mocking a base class method call with Moq

in which the 2nd answer suggests it can be achieved by setting CallBase property to true on the mock object. However it's not clear how this would enable the call to the base class method (Method1 in the above example) to be verified.

Appreciate any assistance with this.

like image 997
aw1975 Avatar asked Apr 19 '16 18:04

aw1975


2 Answers

Unit tests should verify behavior, not implementation. There are several reasons for this:

  • The results are the goal, not how you get the results
  • Testing results allows you to improve the implementation without re-writing your tests
  • Implementations are harder to mock

You might be able to put in hooks or create mocks that verify that the base method was called, but do you really care how the answer was achieved, or do you care that the answer is right?

If the particular implementation you require has side effects that you can verify, then that is what you should be validating.

like image 187
D Stanley Avatar answered Nov 08 '22 18:11

D Stanley


Mocking the base class from the perspective of the derived class is not possible. In your simple example, I would suggest one of the two options.

Option 1: In the event that MyDerivedClass really shouldn't care what MyBaseClass is up to, then use dependency injection! Yay abstraction!

public class MyClass
{
    private readonly IUsedToBeBaseClass myDependency;

    public MyClass(IUsedToBeBaseClass myDependency){
        _myDependency = myDependency;
    }

    public void Method2()
    {
        _myDependency.Method1();
    }
}

Elsewhere in test land...

[TestClass]
public class TestMyDependency {
    [TestMethod]
    public void TestThatMyDependencyIsCalled() {
        var dependency = new Mock<IUsedToBeBaseClass>();
        var unitUnderTest = new MyClass(dependency.Object);
        var unitUnderTest.Method2();
        dependency.Verify(x => x.Method1(), Times.Once);
    }
}

Option 2: In the event that MyDerivedClass NEEDS to know what MyBaseClass is doing, then test that MyBaseClass is doing the right thing.

In alternative test land...

[TestClass]
public class TestMyDependency {
    [TestMethod]
    public void TestThatMyDependencyIsCalled() {
        var unitUnderTest = new MyDerivedClass();
        var unitUnderTest.Method2();
        /* verify base class behavior #1 inside Method1() */
        /* verify base class behavior #2 inside Method1() */
        /* ... */
    }
}
like image 37
Frank Bryce Avatar answered Nov 08 '22 19:11

Frank Bryce