最佳实践 - 在单元测试中设置不带setter的字段

wvp*_*wvp 6 java reflection unit-testing mockito getter-setter

假设您要测试以下课程:

public class SomeService {
  public String someMethod(SomeEntity someEntity) {
    return someEntity.getSomeProperty();
  }
}
Run Code Online (Sandbox Code Playgroud)

SomeEntity看起来像这样:

public class SomeEntity {
  private String someProperty;

  public getSomeProperty() {
    return this.someProperty;
  }
}
Run Code Online (Sandbox Code Playgroud)

您想要做的断言可能如下:

String result = someService.someMethod(someEntity);

assertThat(result).isEqualTo("someValue");
Run Code Online (Sandbox Code Playgroud)

你怎么能让这个测试工作?

1)在SomeEntity类中为'someProperty'添加一个setter.我不认为这是一个很好的解决方案,因为您不会更改生产代码以使测试工作.

2)使用ReflectionUtils设置此字段的值.测试看起来像这样:

 public class TestClass {
      private SomeService someService;

        @Test
          public void testSomeProperty() {
            SomeEntity someEntity = new SomeEntity();
            ReflectionTestUtils.setField(someEntity, "someProperty", "someValue");

            String result = someService.someMethod(someEntity);

            assertThat(result).isEqualTo("someValue");
          }
}
Run Code Online (Sandbox Code Playgroud)

3)在测试类中创建一个扩展SomeEntity类的内部类,并为该字段添加setter.但是,要实现此功能,您还需要更改SomeEntity类,因为该字段应该变为"受保护"而不是"私有".测试类可能如下所示:

public class TestClass {
  private SomeService someService;

  @Test
  public void testSomeProperty() {
   SomeEntityWithSetters someEntity = new SomeEntityTestWithSetters();
    someEntity.setSomeProperty("someValue");

    String result = someService.someMethod(someEntity);

    assertThat(result).isEqualTo("someValue");
  }


  public class SomeEntityWithSetters extends SomeEntity {
   public setSomeProperty(String someProperty) {
     this.someProperty = someProperty;
   } 
  }
}
Run Code Online (Sandbox Code Playgroud)

4)你使用Mockito来模拟SomeEntity.如果您只需要在类中仅模拟一个属性,那么似乎很好,但如果您需要像10个属性那样进行模拟,那该怎么办呢.测试可能如下所示:

public class TestClass {
  private SomeService someService;

  @Test
  public void testSomeProperty() {
    SomeEntity someEntity = mock(SomeEntity.class);
    when(someEntity.getSomeProperty()).thenReturn("someValue");

    String result = someService.someMethod(someEntity);

    assertThat(result).isEqualTo("someValue");
  }
}
Run Code Online (Sandbox Code Playgroud)

krm*_*007 8

您可以使用反射设置值.它不需要对生产代码进行任何更改.

ReflectionTestUtils.setField(YourClass.class,"fieldName",fieldValue);


小智 0

通过 SomeService.someMethod() 的 junit 测试

替代方案 1. 不应使用此选项,因为无需更改编写 junit 的实体。

可以使用替代方案2。

替代方案 3. 再次与 3 相同,无需仅针对 junit 进行扩展。当课程无法延长时怎么办?

替代方案 4. 是的,一个不错的选择。出于同样的原因使用mockito。