Moq 对象不调用方法

Moq object doesn't invoke method

我得到了一个 class,我为其创建了一个模拟,以便我可以对其进行测试。

class 本身看起来像这样:

public class MyData
{
    private string data;
    private string path;
    
     public MyData(string apath)
     {
        this.path = apath;
     }

    public virtual async Task<string> GetData()
    {
        if(IsDataExpired())
        {
            data = await CreateData();
        }
        return data;
    }

    protected virtual bool IsDataExpired() { ... }
    protected virtual async Task<string> CreateData() { ... }
}

测试:

 public void TestData()
    {
        string data = "some data";
        Mock<MyData> dataMock = new Mock<MyData>("path");
               
        dataMock.Protected().Setup<bool>("IsDataExpired").Returns(true);
        dataMock.Protected().Setup<Task<string>>("CreateData").ReturnsAsync(data);
        var dataRes = dataMock.Object.GetData().Result;
        Assert.IsNotNull(dataRes);
    }

问题是由于某种原因 dataRes 在测试结束时为空。我尝试在 class 内部调试,但似乎代码甚至没有进入 GetData 方法并且没有遇到任何断点,并且 dataRes 立即收到空值。

我是不是调用方法不对?为什么不进入方法?

Why won't it enter the method?

默认情况下,Moq 将覆盖 virtual 个成员。

通过将 CallBase 属性 设置为 true

来配置 mock 以调用基本虚拟成员

CallBase = true 将让模拟调用基础 class 实现,如果没有期望(设置)覆盖成员。

另外既然被测成员是异步的,那么测试也应该是异步的

public async Task TestData() {
    //Arrange
    string data = "some data";
    Mock<MyData> dataMock = new Mock<MyData>("path") {
        CallBase = true
    };
           
    dataMock.Protected().Setup<bool>("IsDataExpired").Returns(true);
    dataMock.Protected().Setup<Task<string>>("CreateData").ReturnsAsync(data);

    //Act
    string dataRes = await dataMock.Object.GetData();

    //Assert
    Assert.IsNotNull(dataRes);
}