【问题标题】:Expected invocation on the mock once, but was 0 times With Moq预期在模拟上调用一次,但使用 Moq 时为 0 次
【发布时间】:2016-04-21 14:57:58
【问题描述】:

我收到一个错误

在 mock 上调用一次,但为 0 次

下面是我的代码结构

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 
    }
}

测试类保存地址的测试方法

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 对象但即使这些值也没有设置..不知道出了什么问题。

【问题讨论】:

  • 您永远不会将genAddress 间接传递给SaveAddress

标签: c# unit-testing moq


【解决方案1】:

您正在使用手动创建的 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);
}

【讨论】:

    【解决方案2】:

    您似乎使用“dddd”(4 天)调用 Save,但验证它是使用“ddddd”(5 天)调用的。

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

    var name = "dddd";
    objSaveAddress.Save(name);
    
    genAddress.Verify(a=>a.GenerateAddress(name),Times.Once);
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-03
        • 2021-08-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多