【问题标题】:TDD how can I build this test? Not sure what to verify it againstTDD 我如何构建这个测试?不确定要针对什么进行验证
【发布时间】:2012-10-22 23:29:48
【问题描述】:

我正在使用 nunit、moq 并尝试进行 TDD。

我有返回一些用户帐户的查询。我有另一个查询返回一组条件。

我将遍历每个帐户并根据集合检查每个帐户,并查看用户帐户属于什么条件(如果有)。

public void Test()
{
  var accounts = GetAccounts();
  var conditions = GetConditions();

  foreach(var a in accounts)
 {
    var found = conditions.Where(x => x.condition1 >= a.condition1 && x.condition2 <= a.condition2).FirstOrDefault();

    if(found)
    {
      // move on to next condition in flow chart
    }
    else
    {
       continue;
    }
 }

}

如何在 TDD 中进行测试。我想验证是否找到了正确的条件?我不认为将此作为公共方法是明智的,而且我认为在我的应用程序中有人检查条件没有任何意义。

所以我不确定实际测试什么,因为这个条件稍后会用于计算一个数字,我可以用它来验证是否调用了正确的条件。问题是,这基本上意味着方法的结束,并且数字可能会受到任何其他东西的影响,并且会破坏我对 TDD 的理解(你一次写一个方法,但首先要进行单元测试测试一下)

编辑

是的,这就是我开始做的事情。我做了我的模拟和假物体。并进行了所有设置,但后来我陷入了我将用来验证结果的问题上。 我正在制作的方法很可能会保持无效(它会记录错误或在某些时候更新客户帐户)。它确实是应用程序中唯一的公共方法,因为应用程序将作为计划任务运行(它是一个控制台应用程序),因此它基本上是“运行”方法。它将在所有业务案例的业务层中有许多私有方法。最后,用户要么被跳过,要么如果他们满足条件,他们就会受到惩罚。 罚款将更新到他们的帐户。

是的,我可以将条件方法设为公开或内部,但我认为业务层之外的任何方法都不应该知道它们。它仅与该业务层相关,然后仅在运行该“运行”方法时在其之上。

这就是 TDD 对我来说如此困难的原因。他们说只测试公共方法,如果我说的是一个与用户交互的网站,并且很可能会向用户发送某种反馈(即成功消息/结果)。但是当你有一个应用程序应该作为计划任务运行时,它只通过一个公共方法运行,其余的只是业务规则,我很难弄清楚如何测试它。

什么是 SUT 内部?

【问题讨论】:

  • SUT = 被测系统。在您的情况下,它是规则引擎。我说将 SUT 设为内部,这意味着您应该将规则引擎的封装设为内部(并将内部暴露给单元测试)。

标签: .net tdd nunit moq console-application


【解决方案1】:

与任何测试一样,您需要指定一些虚假的依赖项(在这种情况下是用户和条件),并将您正在测试的函数的输出与预定义的预期结果进行比较(在这种情况下,如果我理解正确,您要验证每个帐户是否具有预期的条件)。

您可以编写一个测试,将假用户列表和假规则列表注入您的 SUT(被测系统),并将实际用户列表及其条件与预期列表进行比较。

您的测试可能如下所示:

[Test]
public void Rules_matcher_with_premium_users_should_have_free_access()
{
    var customer = Mock<IAccount>>);
    var condition = Mock<ICondition>();
    customer.Setup(c => ...); // set up condition
    condition.Setup(co => ...); // set up condition
    var sut = new MyBusinessLogic(customer.object, condition.object);
    var result = sut.DoConditionCheck();

    Assert.AreEqual(condition.object.Id, customer.object.Condition.Id);
}

我在这里所做的是一个测试示例,正如您所说,客户应该有正确的条件。我为条件和客户使用了存根,并假设规则引擎应该工作,客户应该拥有那个条件。

至于封装:根据大多数 TDD 纯粹主义者的说法,您只测试公共 API。其他任何东西都将作为被您测试的公共 API 调用的副作用进行测试。如果它不是公开的,它是一个实现细节,不需要直接测试。如果需要测试,请公开。

我的看法稍微轻松一些。您可以将 SUT 设为内部,并使用 InternalsVisibleTo 属性将其公开以进行单元测试,并指定测试程序集。

【讨论】:

  • 当很难编写测试时,通常是因为生产代码很难测试。如果您想编写可靠的测试来验证操作的结果,而不是实现,您应该重构 SUT 以返回一个值。在您的情况下,我将重构规则引擎以返回具有应用条件或应用条件本身的帐户(根据我的示例)。然后,您可以将您的解决方案构建为一项服务,其主要工作流程包含您可以测试的引擎(功能)。
  • 您可以编写集成测试来验证整个应用程序的结果(即公共方法),同时为执行实际工作的内部函数编写单元测试。您可以将内部结构暴露给测试。我相信这是对实用性的有效让步。只需重构您的内部函数以返回确定性结果,您可以将其与预期结果进行比较。
  • 好吧,我要去申请一次通过 60,000 多个帐户。正如我所说,我可以创建一个返回条件的方法,但问题是我不想将它公开为公共方法或业务层之外的任何东西
  • 最终我会编写综合测试来验证结果,但现在我只是想验证我的逻辑。我不介意将方法公开给测试,但是使用 internal 关键字,我的业务层类在程序集中的所有内容都可以访问该方法,这就是我遇到的问题。
  • 也许我做的太多了,但是您需要将方法(至少)公开给程序集似乎有点不对劲。就像我说的那样,只有服务层应该知道该方法,而实际上它应该只调用这些方法。然而,我已经将它们变成了内部(在这个项目中真的没有差异,然后将其公开,因为只有 2 个项目......控制台应用程序和测试项目)。但是因为我要完成这个项目,所以我以这种方式暴露了它。我仍然不喜欢它,但我希望能够测试它并完成这个项目。我还在找一个
【解决方案2】:

您在评论中提到了流程图。那么,为什么不创建一个流程图对象并对其进行测试。您将有一个像 GetNextStep 这样的方法来接收一个帐户,然后您会看到返回的步骤是您期望的步骤。

【讨论】:

  • 我不关注。是的,我可以将代码移至它自己的方法,但我觉得该方法应该是私有的,并且由于您无法测试 proviate 方法,我仍然遇到同样的问题。我的应用程序有 2 个公共方法,将是一个运行的自动化程序,所有结果都会发布到数据库(什么会被模拟出来)。问题是在满足这些先决条件之前,对象不会被创建一段时间。
  • 我的意思是,您可以在名为 Flowchart 的类中对流程图的概念进行建模。在这个类中,您将有一个名为 GetNextStep 的方法,它接收一个帐户和该帐户的上一步。此方法将包含您要实现的逻辑。您将在单元测试中测试此方法。通过这种方式,您可以对某个帐户进行预期的测试,并且您将从该方法返回步骤。您只需比较它们即可知道该方法是否返回了正确的值。希望对您有所帮助。
猜你喜欢
  • 2017-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 2023-03-08
  • 1970-01-01
  • 2014-02-12
  • 1970-01-01
相关资源
最近更新 更多