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

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

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

这意味着我们不能在set测试中使用get方法,反之亦然 – 您不会测试单个方法的单个代码单元。

鉴于…

假设我们有一个带有字段valuePlainOldJavaObject ,我们想要(由于某种原因)测试setter和getter的有效性。 唯一合适的方法是使用reflection 。

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

 public class PlainOldJavaObject { private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } } 

我现在设置我的测试类来利用reflection; 特别是使用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"); } } 

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

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

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

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

使用Bean Runner API

这将自动测试所有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测试确实有价值,因为它可以捕获拼写错误。 然而,由于代码生成工具导致这些错误不常见,因此应该花费很少的时间。 因此,使用工具执行这些测试而不是自己编写测试是一种很好的做法。

这就是为什么我创建了一个ReflectiveGetterSetterTester ,它有一个方法testAllGetterSetters

ReflectiveGetterSetterTester

结合其他笔记……

  • 无需使用两种测试方法。 使用一个,因为它会使得getter和setter都变得非常有用。
  • 考虑使用Theory来测试一系列有效值( 0, 1, Integer.MAX_VALUE )。 您也可以使用TestedOn在这里传递这些int内联示例
  • 测试错误条件,如传递-1

问题是你无法在任何一个测试中知道问题是在你的getter中还是在你的setter中,因为你必须用一个来测试另一个。 你也可以

  • 用reflection

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

  • 或者不测试getter和setter

我仍然没有足够的经验来说出最好的是什么,但我知道它们都有缺点。