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

2022-09-03 04:44:14

为对象中的实例变量的 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);
}

答案 1

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

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

鉴于...

假设我们有一个字段,我们希望(出于某种原因)来测试 setter 和 getter 的有效性。做到这一点的唯一适当方法是通过使用反射PlainOldJavaObjectvalue

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

public class PlainOldJavaObject {

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

我现在设置了我的测试类来利用反射;专门使用该类: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");
    }

}

在第一个测试中,我通过反射性地访问字段中包含的值来确保读取字段的实例。在不违反声明类*的完整性的情况下,我相信该字段已正确设置。PlainOldJavaObject

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

最终,如果你有很多 setter 和 getter,你将不得不做这样的代码(因为,如果你依赖于你的 setter 和 getter “just work”的假设,就像你在上面的测试中一样,你的测试用例可能是无效的)。

*:请注意,反射是一种快速快速的方式,可以解决未定义行为的极端麻烦,并且您几乎没有对象不变性的保证。你正在从语言中取下收缩包装,正在做一些奇怪而不寻常的事情。自担风险行事。


答案 2

我认为用于测试 getter 和 setter 的方法是完全有效的,恕我直言,我认为这就是 getter-setter 应该被测试的方式。

我听到的一个常见语句是,单元测试应该只测试一个单元,因此,一个类的单个方法。但是,在这种情况下,我们最好将其称为单方法测试。如果可能的话,一个单位应该是一种方法,但更重要的是它是一个用例!

考虑一个这样的类

public class PlainObject {

    void setA(int a) {
    }
 }

在这里,如果您编写任何调用该方法的单元测试,它将通过,因为此方法不执行任何操作。这是完全有效的,因为调用此方法是唯一可能的用例。它不会影响应用程序的行为。

进行一个同时使用 getter 和 setter 的测试是正确的,因为就其本身而言,您无法测试 setter 方法的行为。此外,在你执行获取之前,setter的行为甚至无关紧要。如果我所做的只是调用一个 setter,并且从不获得该值或以任何其他方式使用,那么拥有 setter 就没有意义了。

使用反射或其他花哨的方法只会测试实现。这些方法不测试代码的行为。最后,你最终将代码编写为测试,这是无用的。

我唯一要做的更改是将测试方法的名称从 testSetter 更改为 testAccess,因为您可以读取并更新该值。


推荐