Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Junit测试实例变量的setter和getter_Java_Unit Testing_Junit - Fatal编程技术网

Java Junit测试实例变量的setter和getter

Java Junit测试实例变量的setter和getter,java,unit-testing,junit,Java,Unit Testing,Junit,为对象内实例变量的setter和getter创建测试用例时。最好的方法是什么?在这里,我在测试中使用get和set方法。这是一个糟糕的测试策略吗 /** * Test of setFlightNumber method, of class Flight. */ @Test public void testSetFlightNumber() { System.out.println("setFlightNumber"); int flightNumber = 1000;

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

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

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

鉴于

假设我们有一个
PlainOldJavaObject
,其中有一个字段
,我们希望(出于某种原因)测试setter和getter的有效性。唯一合适的方法是通过

这是我的类声明,它很瘦:

public class PlainOldJavaObject {

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}
我现在设置了我的测试类来利用反射;具体使用
字段
类:

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“正常工作”的假设,就像您在上面的测试中一样,您的测试用例可能是无效的)


*:请注意,反射是一种快速的方法,它会让未定义的行为陷入极端麻烦,而且您几乎无法保证对象的不变性。你把语言的心理包装去掉了,做了一些奇怪和不寻常的事情。继续进行会有您自己的风险。

我相信getter/setter测试确实有价值,因为它可以捕获打字错误。但是,由于代码生成工具的原因,这些错误并不频繁,因此应该在这些错误上花费很少的时间。因此,使用一个工具来执行这些测试,而不是自己编写它们是一个好的实践

有一个库可以帮助:

还有几张便条

  • 不需要使用两种测试方法。使用一个,因为它将同时调整getter和setter的大小
  • 考虑使用
    理论
    测试有效值的范围(
    0,1,Integer.MAX_值
    )。您还可以使用来在线传递这些int
  • 测试错误条件,如通过
    -1

这将自动测试所有getter和setter,确保正确设置了值

testBean

public void testBean(java.lang.Object bean)
              throws java.lang.Exception
Test the properties that have both getters and setters. Exclude those who have been excluded by excludeProperty(String). If the object implements Serializable, do a check to ensure it really is.
Parameters:
bean - the object to test
Throws:
java.lang.Exception - on failure

问题是,在这两个测试中,您都无法知道问题是在getter中还是在setter中,因为您必须使用一个测试另一个。你也可以

  • 使用反射

  • 将您的私有字段标记为受保护,并让您的测试从目标继承

  • 或者不要测试getter和setter

我还没有足够的经验告诉你最好的是什么,
但是我知道它们都有缺点。

我认为用于测试getter和setter的方法是完全有效的,我认为这就是测试getter和setter的方法

我听到的一个常见说法是,单元测试应该只测试一个单元,因此,测试一个类的单个方法。然而,在这种情况下,我们最好称之为单一方法测试。一个单元,如果可能的话,应该是一个方法,但不仅仅是一个用例

考虑这样一个类

public class PlainObject {

    void setA(int a) {
    }
 }
在本例中,如果您编写任何调用该方法的单元测试,它将通过,因为该方法不执行任何操作。这是完全有效的,因为调用此方法是唯一可能的用例。无论如何,它都不会影响应用程序的行为

做一个同时使用getter和setter的测试是正确的,因为单靠它本身无法测试setter方法的行为。此外,在执行get之前,setter的行为甚至都不重要。如果我所做的只是调用一个setter,而从未获得该值或以任何其他方式使用,那么就没有必要使用setter

使用反射或其他奇特的方法只能测试实现。这些方法不会测试代码的行为。最终,您将以测试的形式编写代码,这是无用的


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

为什么要费心测试setter和getter?这是我的第一个问题;除非你的setter/getter所做的比他们所说的要多(这无论如何都是不好的),否则你应该相信这样一个事实:对字段的赋值不会失败。而且,你正在讽刺地测试它们是以相同的方法工作的,所以如果你要测试这个,你只需要一种方法(因为,如果没有反射,你将无法在没有得到它的情况下获得设置的值)。这是实验室的一项要求。我刚刚阅读了一些文章,许多人认为这是毫无意义的。但是让我们只说为了测试需要测试它。在setFlightNumber中使用getFlightNumber方法可以吗?@MariuszS:这使用getter。我个人认为使用getter测试setter比使用refection更合适。我觉得反射会导致脆弱的测试,如果API没有改变,程序员应该能够在不更新测试的情况下重构代码。我认为单元测试应该测试API合同的一部分,而不是底层代码。setter的约定是当调用getter时返回