java - 最佳实践 - 在单元测试中设置一个没有 setter 的字段

标签 java unit-testing reflection mockito getter-setter

假设您有以下要测试的类:

public class SomeService {
  public String someMethod(SomeEntity someEntity) {
    return someEntity.getSomeProperty();
  }
}

SomeEntity 看起来像这样:

public class SomeEntity {
  private String someProperty;

  public getSomeProperty() {
    return this.someProperty;
  }
}

你想做的断言可以是:

String result = someService.someMethod(someEntity);

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

如何使这个测试成功?

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");
          }
}

3) 您在测试类中创建了一个内部类,它扩展了 SomeEntity 类并为此字段添加了 setter。但是,要使其正常工作,您还需要更改 SomeEntity 类,因为该字段应变为“ protected ”而不是“私有(private)”。测试类可能如下所示:

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;
   } 
  }
}

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");
  }
}

最佳答案

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

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

关于java - 最佳实践 - 在单元测试中设置一个没有 setter 的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28758883/

相关文章:

java - Spring Boot 应用程序无法运行 - spring.resources.cache-period 未绑定(bind)

iPhone 单元测试

c# - 无法在 UWP 中获取 ColumnDefinitionCollection 的 "Add"方法

scala - 模式匹配或 Scala 中的 isInstanceOf

haskell - 我可以在运行时从 Haskell 程序中反射(reflect)消息吗?

java - 内存不足错误: PermGen space when starting an embedded Tomcat

Java - 使用类型参数初始化类

Java swing - 如何将我的字段绑定(bind)到模块

angular - Jasmine:期望在异步函数中抛出错误

python - 模拟不适用于 pytest 和 flexmock