Статьи

Ожидаемое правило исключения и статические методы насмешки — JUnit

Сегодня меня попросили использовать сервис RESTful, поэтому я начал внедрять его, следуя правилам Роберта Сесила Мартина для TDD, и наткнулся на новый (по крайней мере, для меня) способ тестирования ожидаемого исключения вместе с сообщением об ошибке, поэтому подумал о том, чтобы поделиться способом, которым я реализовал это как часть этого поста.

Для начала давайте напишем @Test и определим правило, согласно которому наш код будет генерировать конкретное исключение для нашего примера, это EmployeeServiceException, которое мы проверим с помощью ExpectedException, которое предоставит нам более точную информацию об исключении, которое, как ожидается, будет выдано с возможностью проверки сообщение об ошибке, а именно:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassWithStaticMethod.class)
public class EmployeeServiceImplTest {
 
    @InjectMocks
    private EmployeeServiceImpl employeeServiceImpl;
 
    @Rule
    public ExpectedException expectedException = ExpectedException.none();
 
    @Before
    public void setupMock() {
        MockitoAnnotations.initMocks(this);
    }
 
    @Test
    public void addEmployeeForNull() throws EmployeeServiceException {
        expectedException.expect(EmployeeServiceException.class);
        expectedException.expectMessage("Invalid Request");
        employeeServiceImpl.addEmployee(null);
    }
 
}

Теперь мы создадим реализующий класс для нашего @Test, который будет выдавать исключение EmployeeServiceException всякий раз, когда запрос пуст, для меня это EmployeeServiceImpl следующим образом:

EmployeeServiceImpl.java

01
02
03
04
05
06
07
08
09
10
11
public class EmployeeServiceImpl implements IEmployeeService {
 
    @Override
    public String addEmployee(final Request request)
            throws EmployeeServiceException {
        if (request == null) {
            throw new EmployeeServiceException("Invalid Request");
        }
        return null;
    }
}

Далее мы напишем @Test, в котором мы будем имитировать статический метод, который принимает входные параметры с типом возвращаемого значения, используя PowerMockito.mockStatic () , проверяет его с помощью PowerMockito.verifyStatic () и, наконец, выполняет Assert для записи состояния прохождения теста или сбоя, как показано ниже. :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
@Test
    public void addEmployee() throws EmployeeServiceException {
        PowerMockito.mockStatic(ClassWithStaticMethod.class);
        PowerMockito.when(ClassWithStaticMethod.getDetails(anyString()))
                .thenAnswer(new Answer<String>() {
                    @Override
                    public String answer(InvocationOnMock invocation)
                            throws Throwable {
                        Object[] args = invocation.getArguments();
                        return (String) args[0];
                    }
                });
        final String response = employeeServiceImpl.addEmployee(new Request(
                "Arpit"));
        PowerMockito.verifyStatic();
        assertThat(response, is("Arpit"));
    }

Теперь мы предоставим реализацию для нашего @Test внутри EmployeeServiceImpl . Чтобы сделать это, давайте изменим EmployeeServiceImpl, чтобы статический вызов метода был частью инструкции else addEmployee , следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
public class EmployeeServiceImpl implements IEmployeeService {
 
    @Override
    public String addEmployee(final Request request)
            throws EmployeeServiceException {
        if (request == null) {
            throw new EmployeeServiceException("Invalid Request");
        } else {
            return ClassWithStaticMethod.getDetails(request.getName());
        }
    }
}

Где getDetails — статический метод внутри ClassWithStaticMethod :

1
2
3
4
5
6
public class ClassWithStaticMethod {
 
    public static String getDetails(String name) {
        return name;
    }
}

Полный исходный код размещен на github .