package org.magnum.mobilecloud.integration.test;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.magnum.mobilecloud.video.TestData;
import org.magnum.mobilecloud.video.client.VideoSvcApi;
import org.magnum.mobilecloud.video.controller.Application;
import org.magnum.mobilecloud.video.controller.Video;
import org.magnum.mobilecloud.video.controller.VideoSvc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationContextLoader;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
/**
*
* This test shows how to fully setup and configuration a controller (or you could
* setup all controllers) for an integration test. The real Application class is used
* to configure the application. Spring sets up almost all of the supporting infrastructure
* that the Application has when you run it.
*
* A MockMvc or "fake" web interface is create to send requests to your controller and
* validate the responses. Unlike the unit test in VideoSvcTest, integration testing requires
* sending mock HTTP requests to the controller and encoding the test data into JSON before
* the mock HTTP request is sent.
*
* There are a variety of annotations that are used to setup this integration test. These
* annotations will primarily be the same across all of the integration tests for your
* controllers. You can base other integration tests off the test below by simplying
* changing the controller that is @Autowired and passed into MockMvcBuilder.standaloneSetup(..)
*
* @author jules
*
*/
// Tell Spring to setup a web container configuration for testing
@WebAppConfiguration
// Tell JUnit to run using Spring's special JUnit runner
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class })
// This is where you tell Spring the Application or Configuration object to use
@ContextConfiguration(classes = Application.class, loader = SpringApplicationContextLoader.class)
public class VideoSvcIntegrationTest {
// Ask Spring to automatically construct and inject your VideoSvc
// into the test
@Autowired
private VideoSvc videoService;
// This is the mock interface to our application that we will use to
// send mock HTTP requests
private MockMvc mockMvc;
@Before
public void setUp() {
// Setup Spring test in standalone mode with our VideoSvc object
// that it built
mockMvc = MockMvcBuilders.standaloneSetup(videoService).build();
}
// This test is the integration testing equivalent of the
// VideoSvcTest.testVideoAddAndList() test. The key difference is that
// this integration testing version sets up the entire Spring infrastructure
// supporting your application and configures your application using the
// real objects that you specify in your Application class.
@Test
public void testVideoAddAndList() throws Exception {
Video video = TestData.randomVideo();
String videoJson = TestData.toJson(video);
// Send a request that should invoke VideoSvc.addVideo(Video v)
// and check that the request succeeded
mockMvc.perform(
post(VideoSvcApi.VIDEO_SVC_PATH)
.contentType(MediaType.APPLICATION_JSON)
.content(videoJson))
.andExpect(status().isOk())
.andReturn();
// Send a request that should invoke VideoSvc.getVideos()
// and check that the Video object that we added above (as JSON)
// is in the list of returned videos
mockMvc.perform(
get(VideoSvcApi.VIDEO_SVC_PATH))
.andExpect(status().isOk())
.andExpect(content().string(containsString(videoJson)))
.andReturn();
}
}