BDD/TDD模拟数据的棘手方法

6

我和我的同事正在进行一场激烈的争论。我们开始了一个新项目,试图使用BDD。我们都是第一次尝试,不完全理解应该使用哪些实践方法。我们编写了一些规范,现在正在实施代码。由于涉及到大量数据库交互,事情变得非常棘手。我们陷入了如何模拟数据的困境。我们所采用的方法需要模拟方法而不是数据。如果我用代码来展示,这将是最容易理解的方式...

public static void AssignLeadToDistributor(int leadId, int distributorId)
{
    Lead lead = GetById(leadId);
    lead.DistributorId = distributorId;
    Save(lead);
}

基本上,我们需要重写 GetById() 和 Save() 来返回模拟数据以供我们测试。这样做似乎更有意义:

public static void AssignLeadToDistributor(Lead lead, Distributor distributor)
{
   lead.DistributorId = distirbutor.Id;
}

那么我们只需要模拟我们的对象。

显然第二种方法使测试变得更容易。然而,争议在于我们不想在前端代码中获取新的线索和分销商对象,因为仅传递对象的id会更容易。这样可以减少前端代码量。

希望我解释得足够清楚。

你们认为哪种方式更有意义呢?


当然,二进制决策图很棒,但它们并不是最终的下一代技术,可以使我们所知道的一切都过时了...哦,等等,算了。 - Pascal Cuoq
3个回答

8
我认为你遇到的最大问题是因为你正在使用公共静态函数(这在面向对象语言中通常是不好的)。
我建议将此函数移动到Lead对象中,类似于:
public AssignDistributor(int distributorId) {
   this.DistributorId = distributorId;
   this.Save();
}

更易于测试,更符合面向对象编程的代码 =)

3
我们在BDD规范(可执行的故事)中所做的是完全不模拟数据库,而是使用内存数据库(我们使用SQLite)。此外,在任何场景运行之前,我们都会初始化容器。这是因为我们希望我们的BDD规范尽可能地模仿真实世界,同时仍具有普通单元测试的速度。通过以这种方式定义我们的BDD规范,我们发现对单元测试和集成测试的需求减少了,并获得了提高生产力和可理解性的好处(尽管这些指标无法真正衡量)。

这是我们最终采取的路线。它运行得非常好。 - Kevin Wiskia
太好了 :-) 我们也越来越欣赏这种方法。 - Martin R-L

2

我喜欢第二种方法,因为你所说的原因:你可以很容易地为测试模拟参数。你是否在使用依赖注入框架?如果没有,我建议你仍按照依赖注入原则编写代码,以获得更加模块化和易于测试的代码。

我同意Samuel的观点,尽可能避免使用静态方法,否则您将发现很难进行测试驱动。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接