Как использовать свойство интерфейса в моем RestController для возврата данных в моих обработчиках запросов

#java #spring-boot #spring-mvc #junit

#java #весенняя загрузка #spring-mvc #junit

Вопрос:

Я объявил интерфейс как свойство моего @RestController . В этом интерфейсе всего несколько полей / установщиков / получателей.

Реализация RestController и GetMapping выглядят следующим образом:

 @RestController
@EnableAutoConfiguration
public class AccountController {
    private AccountStoreInterface store;

    @GetMapping(value="/account")
    public Account readAccount(@RequestParam("id") String id) throws AccountNotFoundException {

        Account a = store.getAccount(id); 
        if (a.getId().isEmpty()) {
            throw new AccountNotFoundException();
        }

        return a;
    }

    @ExceptionHandler(AccountNotFoundException.class)
    @ResponseStatus(NOT_FOUND)
    public @ResponseBody String handleAccountNotFoundException(AccountNotFoundException ex) {
        return ex.getMessage(); }

    @ExceptionHandler(NullPointerException.class)
    @ResponseStatus(INTERNAL_SERVER_ERROR)
    public @ResponseBody String handleNullPointerException(NullPointerException ex) {
        return ex.getMessage(); 
    }
}
  

Объявление интерфейса выглядит следующим образом:

 public interface AccountStoreInterface {
    public Account getAccount(String id) throws AccountNotFoundException;
    public Account setAccount(String id, Account account) throws AccountConflictException;
}
  

Я хотел бы протестировать это с помощью spring-boot-starter-test и junit4 . Я ожидаю, что следующий тест вернет 500, потому что я не передал ни одного объекта store, который реализует мой интерфейс, поэтому он должен выдавать NullPointerException .

Как мне настроить мои модульные тесты, чтобы протестировать 500 и 404 коды состояния?

Прямо сейчас приведенный ниже тест фактически завершается неудачей, потому что возвращенный статус равен 200, который я не понимаю, как junit получает.

 @RunWith(SpringRunner.class)
@WebMvcTest(AccountController.class)
public class TestAccountController {

    @Autowired private MockMvc mockMvc;
    @Autowired private WebApplicationContext wac;

    @MockBean
    private AccountController accountController;

    @Test
    public void testGetAccountNotFound() throws Exception {
        mockMvc.perform(get("/account?id={id}", "test-account-id-123")
            .accept(APPLICATION_JSON)
            .characterEncoding("UTF-8"))
            .andDo(print())
            .andExpect(status().isNotFound());
    }
}
  

Комментарии:

1. Начните с удаления поля wac (вы его нигде не используете) и поля AccountController (вы его нигде не используете, и оно не должно быть макетным компонентом: вы хотите протестировать свой реальный контроллер, а не макет контроллера). Вы не должны ожидать 404: ресурс действительно существует, вы должны ожидать ошибку 500 из-за исключения NullPointerException. Но какой смысл тестировать код, который гарантированно будет неправильным?

2. Я просто действительно хочу объявить объект, который реализует хранилище моей учетной записи, а затем протестировать возвращенный JSON, но я не могу заставить его возвращать код состояния, который я ожидаю. Я только начал с Java и spring… тест для запроса GET должен начинаться с вставки чего-либо в хранилище, а затем я бы использовал MockMvc для выполнения запроса GET и проверки выходных данных. это то, что я пытаюсь сделать.

3. Прежде всего, уясните себе, что если вы пишете модульный тест или интеграционный тест, то, поскольку вы используете Autowired и SpringRunner , он загружает ApplicationContext и, следовательно, является интеграционным тестом. Но вы тоже используете MockBean . Издевательство используется в модульном тестировании. Итак, исправьте эти вещи, а затем повторно запустите свои тесты.

4. Почему это должно быть. Вы издеваетесь над своим контроллером, поэтому функциональность не вызывается. Вы должны издеваться над AccountStoreInterface вместо этого и @Autowire контроллером.

5. @M.Deinum это похоже на то, что я пытаюсь сделать. Я просто действительно сбит с толку всеми различными аннотациями и тем, что они делают. Исходя из другой среды, я нахожу это немного сложным. Спасибо за подсказку.