Unit test to verify that a base class method is called

前端 未结 3 1103
有刺的猬
有刺的猬 2020-12-11 20:29

I have a base class:

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

and a derived class:

相关标签:
3条回答
  • 2020-12-11 21:16

    What you're describing is not a test of your code, but a test of the behavior of the language. That's fine, because it's a good way to ensure that the language behaves the way we think it does. I used to write lots of little console apps when I was learning. I wish I'd known about unit testing then because it's a better way to go about it.

    But once you've tested it and confirmed that the language behaves the way you expect, I wouldn't keep writing tests for that. You can just test the behavior of your code.

    Here's a real simple example:

    public class TheBaseClass
    {
        public readonly List<string> Output = new List<string>();
    
        public virtual void WriteToOutput()
        {
            Output.Add("TheBaseClass");
        }
    }
    
    public class TheDerivedClass : TheBaseClass
    {
        public override void WriteToOutput()
        {
            Output.Add("TheDerivedClass");
            base.WriteToOutput();
        }
    }
    

    Unit test

        [TestMethod]
        public void EnsureDerivedClassCallsBaseClass()
        {
            var testSubject = new TheDerivedClass();
            testSubject.WriteToOutput();
            Assert.IsTrue(testSubject.Output.Contains("TheBaseClass"));
        }
    
    0 讨论(0)
  • 2020-12-11 21:20

    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.

    0 讨论(0)
  • 2020-12-11 21:28

    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() */
            /* ... */
        }
    }
    
    0 讨论(0)
提交回复
热议问题