实例变量的Setter和getters的Junit测试

use*_*529 13 java junit unit-testing

为对象内的实例变量的setter和getter创建测试用例时.什么是最好的方法?在这里,我在我的测试中使用get和set方法.这会是糟糕的测试策略吗?

/**
 * Test of setFlightNumber method, of class Flight.
 */
@Test
public void testSetFlightNumber() {
    System.out.println("setFlightNumber");
    int flightNumber = 1000;
    Flight instance = new Flight();
    instance.setFlightNumber(flightNumber);
    // TODO review the generated test code and remove the default call to fail.
    assertEquals(instance.getFlightNumber(), flightNumber);
}

/**
 * Test of getFlightNumber method, of class Flight.
 */
@Test
public void testGetFlightNumber() {
    System.out.println("getFlightNumber");
    Flight instance = new Flight();
    int expResult = 1000;
    instance.setFlightNumber(1000);
    int result = instance.getFlightNumber();
    assertEquals(expResult, result);
}
Run Code Online (Sandbox Code Playgroud)

Mak*_*oto 23

单元测试的主要原则是测试一个简单的代码单元 ; 也就是说,每种方法都应该根据自己的优点进行测试.

这意味着我们不能getset测试中使用该方法,反之亦然 - 您不会测试单个方法的单个代码单元.

鉴于...

假设我们有一个PlainOldJavaObject字段value,我们想要(出于某种原因)测试setter和getter的有效性.唯一合适的方法是使用反射.

这是我的类声明,非常瘦:

public class PlainOldJavaObject {

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

我现在设置我的测试类来利用反射; 特别使用Field该类:

public class PlainOldJavaObjectTest {

    @Test
    public void testSetter_setsProperly() throws NoSuchFieldException, IllegalAccessException {
        //given
        final PlainOldJavaObject pojo = new PlainOldJavaObject();

        //when
        pojo.setValue("foo");

        //then
        final Field field = pojo.getClass().getDeclaredField("value");
        field.setAccessible(true);
        assertEquals("Fields didn't match", field.get(pojo), "foo");
    }

    @Test
    public void testGetter_getsValue() throws NoSuchFieldException, IllegalAccessException {
        //given
        final PlainOldJavaObject pojo = new PlainOldJavaObject();
        final Field field = pojo.getClass().getDeclaredField("value");
        field.setAccessible(true);
        field.set(pojo, "magic_values");

        //when
        final String result = pojo.getValue();

        //then
        assertEquals("field wasn't retrieved properly", result, "magic_values");
    }

}
Run Code Online (Sandbox Code Playgroud)

在第一个测试中,我确定通过反射访问该实例的字段中包含的值来读取该字段PlainOldJavaObject.在不违反声明的类*的完整性的情况下,我相信该领域的设置是恰当的.

在第二个测试中,我假设该值已经设置为先前的值,因此设置涉及使用已知的默认值填充该字段.当我读回值时,我断言读回的值是我们知道它最初设置的值.

最后,如果你有很多制定者和吸气剂,你将不得不做这样的代码(因为,如果你依赖于你的定位器和吸气剂"正常工作"的假设,就像你在上面的测试中那样,你的测试案件可能无效).

*:请注意,反射是一种快速而快速的方法,可以通过未定义的行为进入极端麻烦,并且几乎没有对象不变性的保证.你正在采取语言的收缩包装,并做着奇怪和不寻常的事情.继续自担风险.

  • 就个人而言,我觉得使用吸气剂测试定位器比使用反射更合适.我觉得反射会导致脆弱的测试,如果API没有改变,编码器应该能够重构代码而不更新测试.我相信单元测试应该测试API合同的一部分而不是底层代码.setter的契约是在调用getter时返回传递的值.底层代码可以使用"AtomicReference","Optional"或任何其他持有者,仍然符合合同. (5认同)
  • @makoto,确定可能存在病态情况(尽管如果`setFoo(x)`会对`x`的值产生副作用,可能不适合将它称为setter,尽管有名称),但是在典型的情况下,`setFoo(x)`的*only*visible效果应该是`getFoo(x)`返回的值现在不同.并且*contact*可以实现*而不需要在类中具有对应于`foo`的字段,因此反射不一定是检查它的可靠方式.该字段不是联系人的一部分,方法之间的关系是. (4认同)
  • @makoto 但 getter 和 setter 的契约不是他们修改类中的字段。该领域不是公众接触的一部分。公共联系(大概)是在调用 setter 之后,getter 返回该值。这就是需要测试的。 (2认同)