多个单元测试/类的冗余方法

时间:2013-08-07 18:08:48

标签: java unit-testing junit

在主要代码中说,你有这样的东西:

MyClass.java

public class MyClass {
    public List<Obj1> create(List<ObjA> list) {
        return (new MyClassCreator()).create(list);
    }
    // Similar methods for other CRUD operations
}

MyClassCreator.java

public class MyClassCreator {
    Obj1Maker obj1Maker = new Obj1Maker();

    public List<Obj1> create(List<ObjA> list) {
        List<Obj1> converted = new List<Obj1>();
        for(ObjA objA : list)
            converted.add(obj1Maker.convert(objA));
        return converted;
    }
}

Obj1Maker.java

public class Obj1Maker {
    public Obj1 convert(ObjA objA) {
        Obj1 obj1 = new Obj1();
        obj1.setProp(formatObjAProperty(objA));
        return obj1;
    }

    private String formatObjAProperty(ObjA objA) { 
        // get objA prop and do some manipulation on it
    }
}

假设Obj1Maker的单元测试已经完成,并且涉及模拟复杂对象A的方法makeObjAMock()

我的问题:

  1. 对于单元测试MyClassCreator,我该如何测试create(List<ObjA> list)?所有方法实际上都是委托从ObjAObj1的转换并在循环中运行它。转换本身已经过测试。如果我要创建一个ObjA列表并测试Obj1列表中的每个对象,我会回来,我必须将makeObjAMock()复制到MyClassCreator的单元测试中。显然,这将是重复的代码,因此使用verify()足以确保创建(列表列表)有效吗?

  2. 对于单元测试MyClass,它的create(List<ObjA>)方法只是将操作委托给MyClassCreator。我是否真的需要使用完整的测试用例进行测试,还是应该验证是否已调用MyClassCreator的create方法?

  3. 在Obj1Maker的单元测试中,我通过assertEquals(obj1.getProp(), formatObjAProperty(objA))检查了属性Obj1和ObjA是否相互对应。但是,这意味着我必须将私有formatObjAProperty方法的代码从Obj1Maker类复制到其单元测试中。在这种情况下,如何防止代码重复?我不想让这个方法公开/受保护,所以我可以在单元测试中使用它。在这种情况下重复是否可以接受?

  4. 谢谢,对于冗长的问题感到抱歉。

1 个答案:

答案 0 :(得分:0)

我的意见在这里。选择要测试的方法是一件很难的事情。

你必须考虑a)你是否满足你的要求,以及b)当有人愚蠢地在将来改变代码时会出现什么问题。 (实际上,愚蠢的人可能是你。我们都有糟糕的日子。)

我想说,编写新代码以验证两个对象具有两种格式的相同数据将是一个好主意。可能没有理由从私有方法复制代码并复制代码是一个坏主意。请记住,您正在验证要求。因此,如果原始字符串表示“6/30/13”并且重新格式化的字符串表示“2013年6月30日”,我只需对代码进行硬编码:

assertEquals("Wrong answer", "June 30th 2013", obj.getProp());

为边缘情况和错误添加更多断言。 (在我的例子中,使用“2/30/13”和“2/29/12”和“12/1/14”来检查非法日期,闰年日,并且它可能是“第一”而不是“第1”。 )

在create方法的测试中,我可能只是为了容易出错,并确认返回的数组与传入的数组具有相同的数字。我传入的数组将有两个相同的元素和一些不同的元素。我只是检查相同的相同而不同的相同。为什么?因为我们已经知道格式化器的工作原理。

我不会测试构造函数,但会确保一些测试运行代码。确保大多数代码实际运行在测试中以捕获像你错过的空指针这样的愚蠢错误是很好的。

您正在寻找平衡点。

足够的测试,测试足够多的不同的东西,让代码工作感觉良好。

足够的测试,测试显而易见的事情,将来会发现愚蠢的变化。

没有那么多测试需要测试才能永远运行,并且所有开发人员(包括你)都会推迟运行它们,因为他们不想在运行时等待或失去思路。

余额!