Mock — Хотя setup .Возвращает (true), но всегда получает false

#c# #nunit #moq

#c# #nunit #moq

Вопрос:

У меня есть следующий фрагмент кода. Хотя настройка с retrurn true, но значение всегда возвращает false.

Может кто-нибудь посоветовать, как получить значение как true?

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

—-КЛАСС———-

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

Ценю вашу помощь.

Ответ №1:

Есть пара небольших проблем с вашим тестовым кодом.

Сначала позвольте мне показать, как вы должны это реализовать, а затем позвольте мне дать вам некоторые объяснения:

 [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);
}
 
  • Во-первых, я бы предложил использовать несколько более осмысленные имена для ваших тестов. Здесь я использовал заданную структуру When Then, чтобы описать, при каких обстоятельствах (учитывая), если запускается определенное действие (когда), чего я ожидаю (тогда)
  • Я также предлагаю использовать Arrange Act Assert комментарии и , чтобы визуально разделить различные этапы вашего тестового примера
  • Вызовы Setup методов обычно не зависят от конкретных объектов. Причина этого заключается в том, что классы сравниваются по ссылке. Таким образом, даже если у вас есть два, казалось бы, идентичных экземпляра (например: iNApplicationProcessDTOTest и iNApplicationProcessDTO ), они разные. Вот почему фиктивная функция не вызывается.
    • Используйте It.IsAny<T>() вызовы в Setup фазе и используйте конкретные значения в Verify фазе.
  • Если один из методов издеваемого объекта не вызывается SUT (тестируемой системой), то вам это не нужно Setup .
    • Но вы все равно можете убедиться, что он не был вызван ( Verify(..., Times.Never); )

Комментарии:

1. Большое спасибо за ваш ответ. Вы помогли мне больше понять о макете и модульном тестировании. Я новичок в модульном тестировании. Ваш ответ решил мою проблему.