这是模拟存储库实现的正确方法吗?

时间:2013-05-30 13:12:06

标签: c# unit-testing moq

通过单元测试我的存储库界面,我现在正在对我的存储库实现进行单元测试。我发现我嘲笑了很多实现,太过于让我感到安慰。一个例子如下:

Mock<SqlServerDatabaseContext> repoMock = new Mock<SqlServerDatabaseContext>();
repoMock.Setup(foo => foo.QuestionnaireResults).Returns(new List<QuestionnaireResult>() 
{
      new QuestionnaireResult() { Id = 1, Score = 2  },
      new QuestionnaireResult() { Id = 2, Score = 10 }
}.AsEnumerable());

repoMock.Setup(foo => foo.GetNumberOfResults()).Returns(2);

var average = repoMock.Object.CalculateAverage();

Assert.AreEqual(6d, average, "SqlRepository creativity average failed");

......实际实现如下所示:

public class SqlServerDatabaseContext 
{
    ... stuff omitted for brevity ...

    public virtual IEnumerable<QuestionnaireResult> QuestionnaireResults
    {
        get { return dbContext.QuestionnaireResults; }
    }

    public double CalculateAverage()
    {
        var testSum = QuestionnaireResults.Sum(foo => foo.Score);
        var numberOfRespondents = QuestionnaireResults.Count();
        return creativitySum / numberOfRespondents;
    }

  public virtual int GetNumberOfResults()
    {
        return QuestionnaireResults.Count();
    }
}

调用的qa数据库将增长和缩小,超出我的个人控制范围,因此为了测试CalculateAverage方法,我正在模拟实现,以便让我对这个测试中的值感到疑惑。鉴于我对嘲讽的经验不足,你会说上面是一个有效的方法,或者你能指出我更好的方向吗?

提前谢谢。

2 个答案:

答案 0 :(得分:3)

我想说如果它执行CalculateAverage方法,并且您的设置返回数据以允许CalculateAverage的调用独立运行,那么您就完成了单元测试。但请考虑一下......

你有这个SqlServerDatabaseContext,你完全在嘲笑它。在其中,您有一个名为dbContext的成员。从你的例子来看,它的来源似乎并不清楚。但是dbContext实际上是为CalculateAverage提供数据的dbContext。为什么不模仿// arrange var dbContext = new Mock<WhatEverThisContextClassIs>(); dbContext.Setup(foo => foo.QuestionnaireResults) .Returns(new List<QuestionnaireResult() { ... }); var repo = new SqlServerDatabaseContext(dbContext); // act var result = repo.CalculateAverage(); // assert reshult.Should().Be(6)

{{1}}

所以...

  1. 您遵循arrange / act / assert范例
  2. 您将上下文传递给构造函数中的存储库,存储库将其自身依赖于依赖注入,而DI几乎与TDD密切相关
  3. 断言可能不熟悉,请查看FluentAssertions。很好,但不是必需的。

答案 1 :(得分:0)

扩展胡安所说的,你关心断言的部分是正确的是平均值,但当你说:

    var average = repoMock.Object.CalculateAverage();

你要求你的Moq做这项工作。所以,你并没有真正测试系统,只测试你的Mock,如果有人改变平均功能,那对你根本没有帮助。

Juan的测试所带来的好处是,它使用模拟值作为输入来测试用于计算平均值的实际代码;真实的代码正在测试,假的情景/状态被传递给它。