Java Junit测试实例变量的setter和getter
为对象内实例变量的setter和getter创建测试用例时。最好的方法是什么?在这里,我在测试中使用get和set方法。这是一个糟糕的测试策略吗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;
/**
* 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的大小
- 考虑使用
测试有效值的范围(理论
)。您还可以使用来在线传递这些int0,1,Integer.MAX_值
- 测试错误条件,如通过
-1
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时返回