You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Moq模拟基类虚方法并测试子类重写方法

如何测试子类重写方法的验证逻辑,同时模拟基类的数据库操作?

你遇到的问题根源在于:直接Mock子类的GetTitle方法会完全覆盖你要测试的重写逻辑——Moq会直接返回你Setup的结果,根本不会执行Foo类里的if (id <0)验证,也不会调用base.GetTitle。

要解决这个问题,我们需要用部分Mock(Partial Mock):让子类的重写逻辑正常执行,只替换基类中涉及数据库的GetTitle方法。下面是具体的实现方案:

修正后的测试代码

public class FooTests {
    [Fact]
    public void GetTitle_WhenIdIsValid_ReturnsFormattedTitleWithMockedBaseValue() {
        // Arrange
        int validId = 1;
        string mockedBaseTitle = "Mocked DB Title";
        
        // 创建Partial Mock,CallBase=true表示未被Setup的方法会执行真实逻辑
        var fooMock = new Mock<Foo>() { CallBase = true };
        
        // 专门模拟基类的GetTitle方法(通过强制类型转换指定调用基类版本)
        fooMock.Setup(x => ((FooBase)x).GetTitle(It.IsAny<int>())).Returns(mockedBaseTitle);

        var fooInstance = fooMock.Object;

        // Act
        string result = fooInstance.GetTitle(validId);

        // Assert
        // 验证基类方法被正确调用了一次,参数为validId
        fooMock.Verify(x => ((FooBase)x).GetTitle(validId), Times.Once);
        // 验证返回结果符合子类的格式化逻辑
        Assert.Equal($"Valid ID ({mockedBaseTitle})", result);
    }

    [Fact]
    public void GetTitle_WhenIdIsInvalid_ReturnsErrorMessage() {
        // Arrange
        int invalidId = -1;
        // 这里不需要Mock,因为无效ID的逻辑不会调用基类方法
        var fooInstance = new Foo();

        // Act
        string result = fooInstance.GetTitle(invalidId);

        // Assert
        Assert.Equal("Invalid id", result);
    }
}

关键细节说明

  1. CallBase = true的作用:
    这个配置告诉Moq:对于没有被Setup的方法(也就是Foo类重写的GetTitle),执行真实的代码逻辑,而不是返回默认的空值或Mock结果。这样我们就能测试到子类的验证逻辑。

  2. 模拟基类方法的正确姿势:
    通过((FooBase)x).GetTitle(...)的方式,明确告诉Moq我们要替换的是基类的virtual方法,而不是子类的重写版本。这样当子类的GetTitle调用base.GetTitle(id)时,就会执行我们Mock的逻辑,而不是真实的数据库操作。

  3. 拆分测试用例:

    • 有效ID的测试需要Mock基类,验证子类的格式化逻辑和基类调用情况;
    • 无效ID的测试不需要Mock,直接用真实的Foo对象即可,因为这部分逻辑完全不依赖基类的数据库操作。

原来的测试失败,就是因为你直接Mock了子类的GetTitle,跳过了所有你想测试的重写逻辑——现在调整后,就能精准测试子类的验证逻辑,同时隔离基类的数据库依赖了。

内容的提问来源于stack exchange,提问作者Fred

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:11:52