1. Вступление
ReflectionTestUtils является частью среды Spring Test Context. Это набор для основанных на отражении служебных методов, используемых в модуле, и сценариев интеграционного тестирования для установки непубличных полей, вызова непубличных методов и внедрения зависимостей.
В этом руководстве мы рассмотрим, как мы можем использовать ReflectionTestUtils в модульном тестировании, рассмотрев несколько примеров.
2. Зависимости Maven
Давайте начнем с добавления последних версий всех необходимых зависимостей, необходимых для наших примеров, в наш pom.xml :
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.2.RELEASE</version>
<scope>test</scope>
</dependency>
Последние __https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.springframework%22%20AND%20a%3A%22spring-context%22[spring-context], spring-test __dependencies можно загрузить из Maven Центральный репозиторий.
3. Использование ReflectionTestUtils для установки значения непубличного поля
Предположим, что в нашем модульном тесте нам нужно использовать экземпляр класса с закрытым полем без открытого метода установки.
Давайте начнем с его создания:
public class Employee {
private Integer id;
private String name;
//standard getters/setters
}
Обычно мы не можем получить доступ к закрытому полю id , чтобы назначить значение для тестирования, потому что для него нет открытого метода установки.
Затем мы можем использовать метод ReflectionTestUtils.setField , чтобы присвоить значение закрытому члену id :
@Test
public void whenNonPublicField__thenReflectionTestUtilsSetField() {
Employee employee = new Employee();
ReflectionTestUtils.setField(employee, "id", 1);
assertTrue(employee.getId().equals(1));
}
4. Использование ReflectionTestUtils для вызова закрытого метода
Давайте теперь представим, что у нас есть закрытый метод employeeToString в классе Employee :
private String employeeToString(){
return "id: " + getId() + "; name: " + getName();
}
Мы можем написать модульный тест для метода employeeToString , как показано ниже, даже если он не имеет доступа извне класса Employee :
@Test
public void whenNonPublicMethod__thenReflectionTestUtilsInvokeMethod() {
Employee employee = new Employee();
ReflectionTestUtils.setField(employee, "id", 1);
employee.setName("Smith, John");
assertTrue(ReflectionTestUtils.invokeMethod(employee, "employeeToString")
.equals("id: 1; name: Smith, John"));
}
5. Использование ReflectionTestUtils для внедрения зависимостей
Допустим, вы хотите написать модульный тест для следующего компонента Spring с закрытым полем с аннотацией @ Autowired :
@Component
public class EmployeeService {
@Autowired
private HRService hrService;
public String findEmployeeStatus(Integer employeeId) {
return "Employee " + employeeId + " status: " + hrService.getEmployeeStatus(employeeId);
}
}
Теперь мы можем реализовать компонент HRService , как показано ниже:
@Component
public class HRService {
public String getEmployeeStatus(Integer employeeId) {
return "Inactive";
}
}
Кроме того, давайте создадим фиктивную реализацию для класса HRService , используя Mockito .
Мы вставим этот макет в экземпляр EmployeeService и будем использовать его в нашем модульном тесте:
HRService hrService = mock(HRService.class);
when(hrService.getEmployeeStatus(employee.getId())).thenReturn("Active");
Поскольку hrService является закрытым полем без открытого установщика, мы будем использовать метод ReflectionTestUtils.setField , чтобы вставить макет, который мы создали выше, в это личное поле.
EmployeeService employeeService = new EmployeeService();
ReflectionTestUtils.setField(employeeService, "hrService", hrService);
Наконец, наш модульный тест будет выглядеть примерно так:
@Test
public void whenInjectingMockOfDependency__thenReflectionTestUtilsSetField() {
Employee employee = new Employee();
ReflectionTestUtils.setField(employee, "id", 1);
employee.setName("Smith, John");
HRService hrService = mock(HRService.class);
when(hrService.getEmployeeStatus(employee.getId())).thenReturn("Active");
EmployeeService employeeService = new EmployeeService();
//Inject mock into the private field
ReflectionTestUtils.setField(employeeService, "hrService", hrService);
assertEquals(
"Employee " + employee.getId() + " status: Active",
employeeService.findEmployeeStatus(employee.getId()));
}
6. Заключение
В этом руководстве мы показали, как использовать ReflectionTestUtils в модульном тестировании, рассмотрев несколько примеров.
Примеры кода, как всегда, можно найти over на Github .