编写难以进行单元测试的代码

时间:2013-04-10 05:05:54

标签: unit-testing testing

在一次采访中,我被问到“你如何使代码难以进行单元测试?”我最后在编写一个紧密耦合的代码时感到羞愧。谁能告诉我这个问题的正确答案/方法是什么?

5 个答案:

答案 0 :(得分:4)

看一下Mishko的Guide: Writing Testable Code,在你的代码中引入很多这些缺陷,你最终会得到不可测试的代码。

例如:

  • 尽可能多地在构造函数中执行,启动线程,使用循环和ifs
  • 通过创建长链方法调用来打破Demeter的法则
  • 到处使用单身人士,永远不要求依赖,在静态提供者中查找它们
  • 用2k行代码创建神类

答案 1 :(得分:2)

好的答案可能是

  • 访问数据库的代码
  • 根据系统日期时间行事的代码
  • 在同一个方法(单位)中执行多个功能的代码
  • 具有大量编码行为的代码,这取决于另一个未读代码

并且在genral任何代码中,很难/不可能模拟环境,以使其表现出需要测试的方式。

答案 2 :(得分:1)

    使用new运算符的类所需的
  • 创建依赖项 就足够了!这意味着紧密耦合的代码,这是你的答案。
  • 不遵循SOLID principles的代码。

因此,在测试中,您将无法使用Mock对象,因为您自己创建了依赖项并对关系进行了硬编码。

使用dependency injection,您可以使用多态行为,因此在构造函数或方法中传递给它的依赖项上调用某个方法的类不需要知道具体类型。因此,在测试中,您可以传递模拟对象,并且您将能够轻松地测试您的课程。

Misko's Writing testable code解释了我们如何善于编写不可测试的代码以及如何解决它。

示例(JAVA):

//hard to unit test this code as testing class A also requires that ClassB should work properly
//What is ClassB does some I/O or DB operations. This makes unit test a integration test
class classA{
   ClassB b = new ClassB();   //Creating concrete dependencies

}

interface B{
     //implemented by Class B and your mock class that you create for testing
}

class ClassA{
     private B b;

     //Here you can use mocking framework or create a mock class yourself and pass that as argument
     //So the mock class will not do any DB or I/O and makes this unit test
     public classA(B b){
         this.b = b;
     }
}

答案 3 :(得分:1)

这是一个很好的答案。紧密耦合的代码非常难以进行单元测试(并且可能不应该进行单元测试 - 它应该首先重新考虑),因为根据定义,单元测试只能测试某个特定单元。所有对数据库或系统其他组件的调用都应避免单元测试,因为它们违反了这一要求。

说到这一点你也可以提到,集成测试适用于测试具有依赖关系的代码或代码的更大耦合,甚至是基于行为的操作。您可以构建集成测试套件,例如测试REST API,它具有许多依赖性,甚至可以跨越许多技术和多种编程语言。

同样,如果不考虑设计或不使用合适的设计模式,可能会导致极其耦合或依赖的代码,这些代码在没有重新分解或重写的情况下很难或不可能进行单元测试。然后,您可以谈论TDD(测试驱动开发http://en.wikipedia.org/wiki/Test-driven_development)或BDD(行为驱动开发http://en.wikipedia.org/wiki/Behavior-driven_development),这将迫使您从设计测试套件开始并从那里开始工作。

答案 4 :(得分:0)

难以分离的代码 - 多个职责分散在多个职业之间,但没有一个职责完全承担任何责任

看起来非常复杂的代码 - 尝试平均状态机的if / then / else炸弹500行。

在特定领域非常强烈的代码,数学就是一个明显的例子。采用傅里叶变换函数并添加单个单元测试,显示全零变换为全零。 100%的覆盖率,但没有真正测试过。

与错综复杂链接的外部依赖关系强烈耦合的代码。

具有巨大接口的代码可以完成多项任务。