I want test the method like this
@PostMapping(value = "/test")
public String test(@Valid TestModel model) {
return model.getUsername();
}
and the TestModel is this
@Getter
@Setter
public class TestModel {
private MultipartFile[] image1;
private MultipartFile[] image2;
private MultipartFile[] image3;
private String username;
private String password;
}
I can use httpclient to test this but I don't think this is a good idea,so any other methods with spring test?
If, on the other hand you want to set a fast execution unit test without having to start SpringBoot alltogether... read on.
Using @SpringBootTest sets up a full integration testing environment which starts a full SpringBoot instance so it is relatively time consuming when actively developing. Spring MockMVC comes to the rescue as it emulates a servletContainer to a point where you can incorporate any request filtering or exception handling tests in your unit tests suite.
You can configure this setup with the following approach:
Configure a tailored test context: @ContextConfiguration allows you specify the classes you need for your test. Set Mockito MockMvc which moreless emulates a servlet container and set your tests fixture and dependencies.
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {
WebConfig.class,
SomeFilter.class,
HeaderFactory.class,
})
@Slf4j
public class OrganisationCtrlTest {
private MockMvc mvc;
private Organisation coorg;
@Autowired
private SomeFilter someFilter;
@MockBean
private OrganisationSvc service;
@InjectMocks
private OrganisationCtrl controller = new OrganisationCtrl();
//Constructor
public OrganisationCtrlTest() {
}
....
Configure a mock MVC "servlet emulator": register handler beans in the context and build the mockMvc emulator (Note: there are two possible configuration: standaloneSetup or webAppContextSetup; refer to the documentation). The builder rightfully implements the Builder pattern so you can chain configuration commands for exception resolvers and handlers before calling build().
@Before
public void setUp() {
final StaticApplicationContext appContext = new StaticApplicationContext();
appContext.registerBeanDefinition("BusinessExceptionHandler",
new RootBeanDefinition(BusinessExceptionHandler.class, null, null));
appContext.registerBeanDefinition("InternalExceptionHandler",
new RootBeanDefinition(InternalExceptionHandler.class, null,
null));
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(controller)
.setHandlerExceptionResolvers(getExceptionResolver(appContext))
.addFilters(someFilter)
.build();
coorg = OrganisationFixture.getFixture("orgID", "name", "webSiteUrl");
}
....
Run your tests
@Test
public void testGetSingleOrganisationRecordAndSuccess() throws Exception {
System.out.println("testGetSingleOrganisationRecordAndSuccess");
String request = "/orgs/{id}";
log.info("Request URL: " + request);
when(service.getOrganisation(anyString())).
thenReturn(coorg);
this.mvc.perform(get(request)
.accept(VndMediaType.UNITERRA_RFV1_JSON_UTF8)
.header("Accept-Language", "en"))
.andExpect(content().contentType(
.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(content().string(containsString("org")))
.andExpect(content().string(containsString("aName")))
.andExpect(content().string(containsString("aUrl")))
.andDo(print());
}
....
}
Hope this helps.
Jake.
When you test the Controllers, you are probably doing an integration testing. I write Spring MVC based test cases and with Spring boot, more power to @AutoConfigureMockMvc
Reference:
https://docs.spring.io/spring/docs/5.0.5.RELEASE/spring-framework-reference/testing.html#spring-mvc-test-framework
http://www.baeldung.com/spring-boot-testing
It goes something like this after configuration:
@RunWith(SpringRunner.class)
@SpringBootTest(
webEnvironment = WebEnvironment.RANDOM_PORT,
classes = Application.class)
@AutoConfigureMockMvc
@TestPropertySource(
locations = "classpath:test.properties")
public class ControllerTest {
@Autowired
private MockMvc mvc;
@Test
public void test(){
mvc.perform(MockMvcRequestBuilders
.post("/test")
.contentType(MediaType.APPLICATION_JSON).content(content))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andDo(print());
}
It’s really easy with MockMvc. Also you can check your response with JsonPath.
Spring MVC offers a standaloneSetup that supports testing relatively simple controllers, without the need of context.
Build a MockMvc by registering one or more @Controller's instances and configuring Spring MVC infrastructure programmatically. This allows full control over the instantiation and initialization of controllers, and their dependencies, similar to plain unit tests while also making it possible to test one controller at a time.
An example test for your controller can be something as simple as
public class DemoApplicationTests {
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = standaloneSetup(new HelloWorld()).build();
}
@Test
public void testSayHelloWorld() throws Exception {
this.mockMvc.perform(get("/").accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json"));
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void before() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); //构造MockMvc
}
@Test
public void test() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.multipart("/test")
.file(new MockMultipartFile("image1", "filename1.txt", "text/plain", "some xml".getBytes()))
.file(new MockMultipartFile("image1", "filename2.txt", "text/plain", "some xml".getBytes()))
.file(new MockMultipartFile("image2", "filename3.txt", "text/plain", "some xml".getBytes()))
.file(new MockMultipartFile("image2", "filename4.txt", "text/plain", "some xml".getBytes()))
.file(new MockMultipartFile("image2", "filename5.txt", "text/plain", "some xml".getBytes()))
.file(new MockMultipartFile("image1", "filename6.txt", "text/plain", "some xml".getBytes()))
.file(new MockMultipartFile("image3", "filename7.txt", "text/plain", "some xml".getBytes()))
.param("username", "123")
.param("password", "123")
).andExpect(MockMvcResultMatchers.status().is(200));
}
}