Moq - 如何进入真正的方法?

时间:2014-05-15 20:16:32

标签: c# unit-testing moq

我想使用测试数据作为输入进入实际方法。

当调用GetSurveyList时,它不会注意我给它的日期。它总是返回我手动添加到mockModel的所有三个项目。应检查日期并仅返回日期等于或大于输入日期的项目。

如果我介入,我也只能接口。调用的下一步应该是实现接口的代码,但它没有。这是Moq的标准行为吗?我以为它会让你介入?

这是我的代码:

[TestMethod]
public void TestHasListOfSurveys()
{
    var mockRepository = new Mock<ISurveyListRepository>();
    var mockModel = new List<SurveyList>();
    mockModel.Add(new SurveyList { SurveyID = 1, SurveyName = "test1", DeliveryDate = DateTime.Parse("1/1/2014") });
    mockModel.Add(new SurveyList { SurveyID = 2, SurveyName = "test2", DeliveryDate = DateTime.Parse("6/1/2014") });
    mockModel.Add(new SurveyList { SurveyID = 3, SurveyName = "test3", DeliveryDate = DateTime.Parse("12/1/2014") });

    string testDate = DateTime.Today.ToShortDateString();

    mockRepository.Setup(x => x.GetSurveyList(testDate)).Returns(mockModel);

    var testClass = new SurveyListModel(mockRepository.Object);
    var testModel = testClass.GetSurveyList(testDate);

    mockRepository.VerifyAll();

    Assert.IsTrue(testModel.Count > 0);
}

来自存储库的GetSurveyList:

public class SurveyListRepository:ISurveyListRepository

public List<SurveyList> GetSurveyList(String deliveryDateAfterInput)
{
    List<SurveyList> SurveyLists = new List<SurveyList>();
    string error = string.Empty;

    using (OrderingEntities db = DierbergsAppLib.Entities.EntityFactory.GetInstance<OrderingEntities>(
               new DierbergsAppLib.Entities.EntityFactory.EntityFactoryOptions()
               {
                   EntityNameInConfigFile = "OrderingEntities",
                   ConnectionStringCacheManager = new DierbergsAppLib.Entities.WebCacheConnectionStringManager()
               },
               out error))
    {
        DateTime deliveryDateFilter = Convert.ToDateTime(deliveryDateAfterInput);

        var SurveyList = db.uspOrderSurveyListAllStoresGet(deliveryDateFilter);

        foreach (uspOrderSurveyListAllStoresGet_Result viewsurvey in SurveyList)
        {
           // SurveyLists.Add( )
        }
    }

    List<SurveyList> all = SurveyLists.OrderBy(x => x.SurveyDueDate).ToList();
    return all;
}

模型中的GetSurveyList:

公共类SurveyListModel

public List<SurveyList> GetSurveyList(String deliveryDateAfterInput)
{
    return _repository.GetSurveyList(deliveryDateAfterInput);
}

2 个答案:

答案 0 :(得分:2)

测试是代码的规范。让我们考虑一下您尝试通过此测试指定的SurveyListModel行为的情况。在这种情况下,逻辑非常简单:

  

SurveyListModel应该从存储库返回指定日期的调查

因此,如果您停下来思考,那么您就不应该验证返回调查的日期。 SurveyListModel职责不涉及以任何方式修改存储库响应。它应该执行以下操作 - 将日期参数传递给存储库的一个特定方法,并将存储库响应返回给调用者。没有其他的。那是你应该验证的。

var repositoryMock = new Mock<ISurveyListRepository>();
string date = DateTime.Today.ToShortDateString();
repositoryMock.Setup(r => r.GetSurveyList(date)).Returns(CreateTestSurveys());
var model = new SurveyListModel(repositoryMock.Object);

var surveys = model.GetSurveyList(date);

repositoryMock.VerifyAll();
CollectionAssert.AreEqual(CreateTestSurveys(), surveys);

此测试验证

  • 调查列表调用了正确的存储库方法(如果没有调用方法,验证将失败)
  • 传递了正确的日期(如果SurveyListModel将不同的日期传递给存储库,则不会执行安装)
  • 调查列表返回与存储库完全相同的调查(如果SurveListModel将返回不同的调查,或以任何方式修改存储库响应,则断言应该失败)。

您应该明白,在这种情况下,存储库返回的内容并不重要。它可以是任何日期的调查,也可以是上面的空列表。您应该只验证SUT返回的完全相同的集合。

注意:使用DateTime传递日期值。

答案 1 :(得分:1)

mockRepository.Setup(x => x.GetSurveyList(testDate)).Returns(mockModel);

这会将您的模拟存储库设置为在GetSurveyList(testDate)时返回完整模型,这意味着将忽略该日期。据推测,SurveyListModel期望只返回传递给该方法的日期SurveyList

如果您希望它做正确的事情,那么只包含一个mockModel.Add行,其中包含您希望模拟存储库在测试中实际返回的数据。

但是,既然您已经发布了正在测试的代码,那么很明显这个测试毫无意义。你正在嘲笑实际完成所有工作的代码!您正在“测试”的所有方法都是返回模拟数据。

另外,请勿使用DateTime.Today作为测试日期,否则明天测试可能无效!