模拟 - 虽然设置 .Returns(true) 但总是得到 false

Mock - Although setup .Returns(true) but always get false

我有如下代码片段。虽然设置为 retrurn true 但值始终 return false.

有人可以建议如何将值检索为 true 吗?

public interface IDatabaseService
  {
    bool ProcessSQL(INApplicationProcessDTO inApplicationProcessDTO, string connectionString, string storedProcedureName);
    bool CompleteRun(INApplicationProcessDTO inApplicationProcessDTO, string connectionString, string storedProcedureName);
  }

----CLASS------------

public static class INHelper
{
    public static bool CompleteRun(INApplicationProcessDTO inApplicationProcessDTO, string connectionString = null, IDatabaseService databaseService = null)
    {
      if (inApplicationProcessDTO == null)
      {
        return false;
      }
      if (inApplicationProcessDTO.Data == null)
      {
        return false;
      }
      const string storedProcedureName = "PSP_PWS_INApplication_Application_Process_CompleteRun";

      // Get Connection String to Parity4 Database from Parity4 WebService Web.config
      if (connectionString == null)
      {
        if (ConfigurationManager.ConnectionStrings["ConnectionString"] != null)
        {
          connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
        }
      }
      if (string.IsNullOrWhiteSpace(connectionString))
      {
        return false;
      }

      if (databaseService == null)
      {
        databaseService = new DatabaseService();
      }
      //Why always return false line below
      return databaseService.CompleteRun(inApplicationProcessDTO, connectionString, storedProcedureName);
    }
}

----测试方法----

public void When_CompleteRun_ConnectionValid_Expect_True()
    {
      var iNApplicationProcessDTOTest = new INApplicationProcessDTO()
      {
        Data = new System.Xml.Linq.XDocument(),
        ErrorCount = 0,
        Errors = ""
      };

      Mock<IDatabaseService> iDatabaseService = null;
      iDatabaseService = new Mock<IDatabaseService>();
      iDatabaseService.Setup(t => t.CompleteRun(iNApplicationProcessDTOTest, "test", "test")).Returns(true);
      iDatabaseService.Setup(t => t.ProcessSQL(iNApplicationProcessDTOTest, "test", "test")).Returns(true);

      var iNApplicationProcessDTO = new INApplicationProcessDTO()
      {
        Data = new System.Xml.Linq.XDocument(),
        ErrorCount = 0,
        Errors = ""
      };
      var actual = INHelper.CompleteRun(iNApplicationProcessDTO, "a", iDatabaseService.Object);
      //actual always false although Returns(true) in Setup
      Assert.AreEqual(true, actual);
    }        

感谢您的帮助。

您的测试代码有几个小问题。

首先让我展示你应该如何实现它,然后让我给你一些解释:

[Fact]
public void GivenAFlawlessDatabaseService_WhenICallCompleteRun_ThenItCallsTheUnderlyingServicesCompleteRun()
{
    //Arrange
    const string connectionString = "a";
    var iDatabaseService = new Mock<IDatabaseService>();

    iDatabaseService
        .Setup(db => db.CompleteRun(It.IsAny<INApplicationProcessDTO>(), It.IsAny<string>(), It.IsAny<string>()))
        .Returns(true);

    var iNApplicationProcessDTO = new INApplicationProcessDTO
    {
        Data = new XDocument(),
        ErrorCount = 0,
        Errors = ""
    };

    //Act
    var actual = INHelper.CompleteRun(iNApplicationProcessDTO, connectionString, iDatabaseService.Object);
    
    //Assert
    Assert.True(actual);
    iDatabaseService.Verify(db => db.CompleteRun(iNApplicationProcessDTO, connectionString, "PSP_PWS_INApplication_Application_Process_CompleteRun"), Times.Once);
    iDatabaseService.Verify(db => db.ProcessSQL(It.IsAny<INApplicationProcessDTO>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
  • 首先,我建议为您的测试使用更有意义的名称。在这里,我使用了一个 Given When Then 结构来描述在什么情况下(给定)如果触发特定操作(何时)我会期望什么(然后)
  • 我还建议使用 ArrangeActAssert 注释来直观地分隔测试用例的不同阶段
  • Setup 方法调用通常不依赖具体对象。其背后的原因是 类 是通过引用进行比较的。因此,即使您有两个看似相同的实例(例如:iNApplicationProcessDTOTestiNApplicationProcessDTO),它们也是不同的。这就是为什么不调用模拟函数的原因。
    • Setup阶段使用It.IsAny<T>()调用,在Verify阶段使用具体值。
  • 如果模拟对象的方法之一未被 SUT(被测系统)调用,则您不需要 Setup 它。
    • 但是你仍然可以验证它没有被调用(Verify(..., Times.Never);)