预期在 mock 上调用一次,但为 0 次 With Moq

Expected invocation on the mock once, but was 0 times With Moq

我遇到错误

Invocation on the mock once, but was 0 times

下面是我的代码结构

public class GenerateAddress : IGenerateAddress 
{
    public GenerateAddress(IAddress createAdd, IValidate validate) {
       //constructor 
    }

    public Address GetAddressFromA(string name){..}
}

public class SaveAddress : ISaveAddress 
{
    public SaveAddress(IGenerateAddress generateaddress) {
        //constructor 
    }

    public bool Save(string name)
    {
        var address = generateaddress.GetAddressFromA(name);
        ......
        //Rest of the code to save 
    }
}

要测试的测试方法Class保存地址

public void TestVerifyGetAddressIsCalled()
{
    var mockIAddress = new Mock<IAddress>();
    var mockValidate = new Mock<IValidate>();

    var genAddress = new Mock<IGenerateAddress>();

    var objGenAdress = new GenerateAddress(mockIAddress.Object, mockValidate.Object) // 

    var objSaveAddress = new SaveAddress(objGenAdress);

    objSaveAddress.Save("dddd");

    //Verify if IGenerateAddress 'GenerateAddress' is called

    genAddress.Verify(a=>a.GenerateAddress("ddddd"),Times.Once); // Throws Excepted Invocation 
}

我需要验证是否调用了 GenerateAddress。我也做了 Setup 并将值分配给 Address 对象,但即使这些值也没有设置..不知道出了什么问题。

看起来您是用 'dddd'(4 天)调用 Save,但验证它是用 'ddddd'(5 天)调用的。

将真实数据放在变量中并在两种情况下都引用它更安全:

var name = "dddd";
objSaveAddress.Save(name);

genAddress.Verify(a=>a.GenerateAddress(name),Times.Once);

您正在使用手动创建的 IGenerateAddress (objGenAdress) 和 SaveAddress 而不是模拟的 genAddress

另外考虑到 SUT 是 SaveAddress,它只需要 IGenerateAddress,不需要其他模拟。

public void TestVerifyGetAddressIsCalled() { 
    //Arrange
    var genAddress = new Mock<IGenerateAddress>();

    var objSaveAddress = new SaveAddress(genAddress.Object);

    var name = "dddd";

    //Act
    objSaveAddress.Save(name);

    //Assert
    //Verify if 'IGenerateAddress.GenerateAddress' is called    
    genAddress.Verify(a => a.GenerateAddress(name), Times.Once);
}

我认为在选择回复后,如果我们重构代码首先创建 SaveAddress class 作为模拟并传递参数 genAddress 并将 CallBase 属性 设置为 true。此 属性 的默认值为 false。如果你不使用这个参数你的方法调用 returns null 并且你得到 this.post title error.

        var genAddress = new Mock<IGenerateAddress>();

        var objSaveAddress = new Mock<SaveAddress>(genAddress.Object){CallBase = true};

        var name = "dddd";

        //Act
        objSaveAddress.Object.Save(name);

        //Assert
        //Verify if IGenerateAddress 'GenerateAddress' is called    
        genAddress.Verify(a => a.GetAddressFromA(name), Times.Once);