web-dev-qa-db-ja.com

Spring Framework TEST RESTful Webサービス(コントローラー)オフライン、つまりサーバーなし、データベースなし

JSONを消費して生成する非常にシンプルなRESTfulコントローラーがあります。このコントローラーをオフラインでテストする必要があります。つまり、サーバーが実行されておらず、データベースも実行されていません。そして、私は解決策を見つけることができないために気が狂います。私の最初のテストケースには次のものが含まれます。

  • テストREST URI、つまりGET、POST、PUT、DELETE-送信されたデータに対して返されたデータをアサートできる必要があります。
  • アサートはJSONデータをテストします

私は次のURIを持っています:

  • / pcusers-すべてのユーザーを返します
  • / pcusers/{id}-特定のユーザーを返します
  • / pcusers/create/{pcuser}-ユーザーをdbに追加します
  • / pcusers/update/{pcuser}-ユーザーを更新します
  • / pcusers/delete/{id}-ユーザーを削除します

注:これは一般的なMVCアプリケーションではありません。ビューがありません。 JSONを吐き出し、JSON形式のデータを消費する純粋なRESTコントローラーがあります。

誰かが私を正しい方向に導くことができれば本当にありがたいです。

私のコードがどのように見えるかを明確にするために:

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

PDATE(2/5/2012):調査の結果、spring-test-mvcというSpringフレームワークに出くわしました。それは非常に有望に見えます、そして私はこれで良いスタートを切ることができました。しかし今、私は新しい問題を抱えています。 GETリクエストを "/ pcusers/{id}"に送信すると、そのマッピングの処理を担当するreadメソッドに制御が渡されます。そのメソッドの中には、読み取りを行うpcUserServiceがあります。ここで問題は、このテストを実行すると、実際のコントローラー内のpcUserServiceインスタンスがNULLになることです。したがって、NULLオブジェクトでreadを呼び出すことができないため、クラッシュすることになります。

これが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());
    }
}
15
jsf

ここにいくつかのアイデアを与えるべき1つの提案があります。あなたはSpringJUnit4ClassRunner@ContextConfigurationに精通していると思います。 PcUserControllerとモックされたPcUserServiceを含むテストアプリケーションコンテキストを作成することから始めます。以下のPcUserControllerTestクラスの例では、Jacksonを使用して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);
}
15
matsev