Spring Framework TEST RESTful веб-служба (контроллер) в автономном режиме, т.е. нет сервера, нет базы данных - PullRequest
15 голосов
/ 04 февраля 2012

У меня очень простой RESTful Controller, который потребляет и производит JSON.Мне нужно проверить этот контроллер в автономном режиме, т.е. ни один сервер не работает, ни одна база данных не работает.И я схожу с ума от того, что не могу найти решение.Мои начальные тесты будут включать в себя:

  • Тестирование REST URI, т.е. GET, POST, PUT, DELETE - я должен иметь возможность утверждать данные, возвращенные против отправленных данных.
  • Assert будет тестировать JSONdata

У меня есть следующие URI:

  • / pcusers - возвращает всех пользователей
  • / pcusers / {id} - возвращает определенного пользователя
  • / pcusers / create / {pcuser} - Добавить пользователя в db
  • / pcusers / update / {pcuser} - Обновить пользователя
  • / pcusers / delete / {id} - УдалитьПользователь

ПРИМЕЧАНИЕ. Это НЕ типичное приложение MVC.У меня нет просмотров.У меня есть чистый контроллер REST, который выплевывает JSON и потребляет данные в формате JSON.

Если бы кто-то мог направить меня в правильном направлении, был бы очень признателен.

Просто чтобы было понятно, как мой кодвыглядит так:

@Controller
@RequestMapping("/pcusers")
public class PcUserController {
    protected static Logger logger = Logger.getLogger(PcUserController.class);

    @Resource(name = "pcUserService")
    private PcUserService pcUserService;

    @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
    @ResponseBody
    public List<PcUser> readAll() {
        logger.debug("Delegating to service to return all PcUsers");
        return pcUserService.readAll();
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET, consumes = "application/json", produces = "application/json")
    @ResponseBody
    public PcUser read(@PathVariable String id) {
        logger.debug("Delegating to service to return PcUser " + id);
        return pcUserService.read(id);
    }

    @RequestMapping(value = "/create/{pcUser}", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
    @ResponseBody
    public boolean create(@PathVariable PcUser pcUser) {
        logger.debug("Delegating to service to create new PcUser");
        return pcUserService.create(pcUser);
    }

    @RequestMapping(value = "/update/{pcUser}", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
    @ResponseBody
    public boolean update(@PathVariable PcUser pcUser) {
        logger.debug("Delegating to service to update existing PcUser");
        return pcUserService.update(pcUser);
    }

    @RequestMapping(value = "/delete/{id}", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
    @ResponseBody
    public boolean delete(@PathVariable String id) {
        logger.debug("Delegating to service to delete existing PcUser");
        return pcUserService.delete(id);
    }
}

ОБНОВЛЕНИЕ (2/5/2012): После некоторых исследований я наткнулся на среду Spring под названием spring-test-mvc .Это выглядит очень многообещающе, и мне удалось хорошо начать с этого.Но теперь у меня новая проблема.Когда я отправляю запрос GET в «/ pcusers / {id}», управление передается методу read , который отвечает за обработку этого отображения.Внутри этого метода у меня есть pcUserService , который выполняет чтение.Теперь проблема в том, что когда я запускаю этот тест, экземпляр pcUserService внутри реального контроллера равен NULL;и поэтому он завершается сбоем, поскольку чтение не может быть вызвано для объекта NULL.

Вот PcUserControllerTest код:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/applicationContextTest.xml")
public class PcUserControllerTest {

    @Autowired
    PcUserService pcUserService;

    @Autowired
    PcUserController pcUserController;

    PcUser pcUser;

    @Before
    public void setUp() throws Exception {
        pcUser = new PcUser("John", "Li", "Weasley", "john", "john", new DateTime());

        pcUserService.create(pcUser);
    }

    public void tearDown() throws Exception {
        pcUserService.delete(pcUser.getId());
    }

    @Test
    public void shouldGetPcUser() throws Exception {
        standaloneSetup(pcUserController)
                .build()
                .perform(get("/pcusers/" + pcUser.getId()).accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }
}

1 Ответ

15 голосов
/ 04 февраля 2012

Вот одно предложение, которое должно дать вам несколько идей. Я предполагаю, что вы знакомы с SpringJUnit4ClassRunner и @ContextConfiguration. Начните с создания контекста тестового приложения, который содержит PcUserController и макет PcUserService. В приведенном ниже примере PcUserControllerTest класс Джексон используется для преобразования сообщений JSON, а Mockito - для насмешек.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(/* Insert test application context here */)
public class PcUserControllerTest {

    MockHttpServletRequest requestMock;
    MockHttpServletResponse responseMock;
    AnnotationMethodHandlerAdapter handlerAdapter;
    ObjectMapper mapper;
    PcUser pcUser;

    @Autowired
    PcUserController pcUserController;

    @Autowired
    PcUserService pcUserServiceMock;

    @Before
    public void setUp() {
        requestMock = new MockHttpServletRequest();
        requestMock.setContentType(MediaType.APPLICATION_JSON_VALUE);
        requestMock.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);

        responseMock = new MockHttpServletResponse();

        handlerAdapter = new AnnotationMethodHandlerAdapter();
        HttpMessageConverter[] messageConverters = {new MappingJacksonHttpMessageConverter()};
        handlerAdapter.setMessageConverters(messageConverters);

        mapper = new ObjectMapper();
        pcUser = new PcUser(...);

        reset(pcUserServiceMock);
    }
}

Теперь у нас есть весь код, необходимый для создания тестов:

@Test
public void shouldGetUser() throws Exception {
    requestMock.setMethod("GET");
    requestMock.setRequestURI("/pcusers/1");

    when(pcUserServiceMock.read(1)).thenReturn(pcUser);

    handlerAdapter.handle(requestMock, responseMock, pcUserController);

    assertThat(responseMock.getStatus(), is(HttpStatus.SC_OK));
    PcUser actualPcUser = mapper.readValue(responseMock.getContentAsString(), PcUser.class);
    assertThat(actualPcUser, is(pcUser));
}


@Test
public void shouldCreateUser() throws Exception {
    requestMock.setMethod("POST");
    requestMock.setRequestURI("/pcusers/create/1");
    String jsonPcUser = mapper.writeValueAsString(pcUser);
    requestMock.setContent(jsonPcUser.getBytes());

    handlerAdapter.handle(requestMock, responseMock, pcUserController);

    verify(pcUserServiceMock).create(pcUser);
}
...