添加静态方法以便于清洁单元测试 - 良好实践?

时间:2011-11-17 19:44:30

标签: java unit-testing scala

说我有这个班:

class MyClass {
    private String s;
    // more attributes here
    public MyClass(String s, /*more constructor params*/)  {...}

    public String myMethod(String s) {
        //complex logic here
    }
}

要进行单元测试myMethod()我需要创建整个对象(需要构造许多参数等),而方法只使用s。

Altenatelly我可以添加一个静态方法:

class MyClass {
    private String s;
    // more attributes here
    public MyClass(String s, /*more constructor params*/)  {...}

    public String myMethod(String s) {
        return myStaticMethod(s);
    }

    public static myStaticMethod(String s) {
        //complex logic here
    }
}

现在我可以轻松测试“复杂逻辑”,而无需创建对象。 someStaticMethod(String s)应该对课程没有副作用。 所以我添加了一个额外的方法只是为了便于测试。 这是一个好习惯吗?

7 个答案:

答案 0 :(得分:5)

所以,你已经把一个复杂的方法作为一个对象的一个​​成员,即使它有 nothing 与该实例没什么关系?

是的,我同意你应该使用不同的设计。 可能是该类中的静态方法,或者它自己的类中的因子。 它可能是实现“策略”模式的对象的方法。正确的决定取决于变革的可能性。


也许是这样的:

class ComplexLogician {

  String myMethod(String a, String b) {
    /* Complex logic here. */
  }

}

class MyClass {

  private String s;

  private final ComplexLogician logic;

  /* More attributes here... */

  MyClass(String s, ComplexLogician logic, /* More parameters... */)  {...}

  String myMethod(String b) {
    return logic.myMethod(s, b);
  }

}

答案 1 :(得分:3)

我认为最好不要使方法成为静态,而是在“Before”方法中构造对象一次,该方法将在测试类中的每个测试之前运行。像这样的东西

public class SampleTestSuite  {
    private MyClass myClass;

    @Before
    public void startUp(){
    myClass = new MyClass();//Will be called before each test method is called.

    }

    @Test
    public void testNavigationSucceeded() {
        assert...
    }

    @Test
    public void secondTest() {
        assert...
    }

    @After
    public void tearDown() {

    }

}

答案 2 :(得分:2)

如果方法可以是静态的,那么它应该是静态的,无论你需要它进行测试还是其他什么。您可以在Eclipse中打开警告。 Eclipse会向您发出警告,然后提供有关非静态方法的警告。

答案 3 :(得分:2)

更改生产代码并暴露其“胆量”以便您可以对其进行测试是一种非常糟糕的做法。它破坏了封装,如果你的代码首先是不可测试的,那通常意味着它需要重构。

您希望以静态方法移动的“复杂逻辑”肯定会有利于正确的OO处理。 让一个专家级来处理那个逻辑或一组类,将它们注入到MyClass通过界面,单独的关注点,你的测试将变得更加容易。

更好的是,使用模拟框架开始测试(TDD),这将有机地推动一个好的设计,而不需要静态方法或类似的黑客。

示例:假设您的MyClass需要对其中一个参数进行大量转换(在您的情况下,String s才能使用它。所以您想要提取将处理转换为静态方法?而不是向您的类添加一个依赖项,例如,StringTransformer(相应地重命名),它是您想要的实际实现的接口。拥有方法transform(String s)在变压器中,它将包含您想要的逻辑。然后使用常规方法测试您的实现,完成工作。并且您实际上使您的设计更好。

答案 4 :(得分:1)

我经常将类的一部分功能写为包受保护的静态方法,并根据需要传入字段值。它允许您全面测试功能,而无需将其拆分为单独的类。它可以提供全面的测试覆盖,而不会增加太多的复杂性。

答案 5 :(得分:0)

一般来说,暴露任何超出类所期望功能的功能并不是一种好习惯。由于其他客户端可能已经开始使用代码,因为这种方法是公开的,因此这将阻碍远离该逻辑。另一个选择是使函数受到保护,以便在测试层次结构中的同一个包中,可以编写测试用例。但是,我会选择通过形成一个基础对象来编写测试用例,并继续更改其中的输入和输出集,而不是使用这些解决方法。

答案 6 :(得分:0)

如果您只测试静态方法,那么您将保留实例方法。您可以改为更改实例方法,以便对其进行测试。如果您在此处发布特定案例的更多详细信息或作为新问题,我相信有人会帮助您使其可测试。