单元测试,以验证是否调用了基类方法

本文关键字:基类 类方法 调用 是否 验证 单元测试 | 更新日期: 2024-10-23 01:37:42

我有一个基类:

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

和一个派生类:

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

我想为Method2编写一个单元测试,以验证它是否在基类上调用Method1。我用Moq作为我的嘲讽库。这可能吗?

我发现了一个相关的SO链接:

用Moq模拟基类方法调用

其中第二个答案表明可以通过在mock对象上将CCD_ 3属性设置为true来实现。然而,尚不清楚这将如何验证对基类方法(上例中为Method1)的调用。

感谢在这方面提供的任何帮助。

单元测试,以验证是否调用了基类方法

单元测试应该验证行为,而不是实现。这有几个原因:

  • 结果是目标,而不是如何获得结果
  • 测试结果允许您在不重新编写测试的情况下改进实现
  • 实现更难模仿

可能能够放入钩子或创建mock来验证是否调用了基本方法,但您真的关心如何获得答案,还是关心答案是否正确?

如果您需要的特定实现具有可以验证的副作用,那么就是您应该验证的。

从派生类的角度模拟基类是不可能的。在你的简单例子中,我建议两种选择中的一种。

选项1:如果MyDerivedClass真的不在乎MyBaseClass在做什么,那么就使用依赖注入!抽象!

public class MyClass
{
    private readonly IUsedToBeBaseClass myDependency;
    public MyClass(IUsedToBeBaseClass myDependency){
        _myDependency = myDependency;
    }
    public void Method2()
    {
        _myDependency.Method1();
    }
}

在试验区的其他地方。。。

[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);
    }
}

选项2:如果MyDerivedClass需要知道MyBaseClass在做什么,则测试MyBaseClass在做正确的事情

在备选试验区。。。

[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() */
        /* ... */
    }
}

您所描述的不是对代码的测试,而是对语言行为的测试。这很好,因为这是一个很好的方式来确保语言按照我们认为的方式运行。当我学习的时候,我曾经写过很多小的控制台应用程序。我希望我当时知道单元测试,因为这是更好的方法

但一旦你测试了它,并确认语言的行为符合你的预期,我就不会继续为此编写测试了。您可以只测试代码的行为。

这里有一个非常简单的例子:

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();
    }
}

单元测试

    [TestMethod]
    public void EnsureDerivedClassCallsBaseClass()
    {
        var testSubject = new TheDerivedClass();
        testSubject.WriteToOutput();
        Assert.IsTrue(testSubject.Output.Contains("TheBaseClass"));
    }