简体   繁体   中英

Testing with MockMvc into SpringBoot

I have a problem with MockMvc into Spring (with Spring Boot). I have a small code to learn Testing

import static org.hamcrest.Matchers.containsString;
import static     org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class ApplicationTest04_ownServer {

@Autowired
private MockMvc mockMvc;

@Test
public void shouldReturnDefaultMessage() throws Exception {
    this.mockMvc
    .perform(get("/"))
    .andDo(print())
    .andExpect(status().isOk())
    .andExpect(content().string(containsString("Hello")));
}

OK. Mi pom.xml is this

[...]
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.19.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>org.springframework</groupId>
<artifactId>Prueba</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>Prueba</name>

<properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>compile</scope>
    </dependency>

</dependencies>

I have several test. The works, but I have a problem with test with Mock Object or similar. For example, in the test, the controller response me a text.

@Controller
public class HomeController {

    @RequestMapping("/")
    public @ResponseBody String greeting() {
        return "Hello";
    }

}

In the test (the first code above), this is the code

@Test
public void shouldReturnDefaultMessage() throws Exception {
    this.mockMvc
    .perform(get("/"))
    .andDo(print())
    .andExpect(status().isOk())
    .andExpect(content().string(containsString("Hello")));
}

So, I expect that the response of controller was the same that the response of the test ("hello") but the Junit test is wrong.

java.lang.SecurityException: class "org.hamcrest.Matchers"'s signer information does not match 

I print the result

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /
       Parameters = {}
          Headers = {}

Handler:
             Type = hello.HomeController
           Method = public java.lang.String hello.HomeController.greeting()

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

    ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
         Headers = {Content-Type=[text/plain;charset=UTF-8], Content-Length=[5]}
     Content type = text/plain;charset=UTF-8
             Body = Hello
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /
       Parameters = {}
          Headers = {}

Handler:
             Type = hello.HomeController
           Method = public java.lang.String hello.HomeController.greeting()

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = {Content-Type=[text/plain;charset=UTF-8], Content-Length=[5]}
     Content type = text/plain;charset=UTF-8
             Body = Hello
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

The body response is hello, isn`t is? Any idea?

Observation: This example works in Eclipse Neon but now I use the last version of Eclipse. I had a lot of error (the most of type don't appear: MockMvc, SpringRunner, SpringBootTest, etc.) The solution was to change the scope of the dependency (test --> compile). Now this is the dependency

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>compile</scope>
    </dependency>

Can it have something to do with the problem?

Thanks in advance

The scope of dependency should be test only. As per maven documentation below is the description for scope = test

  • test

This scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases

As highlighted in comments , dont use war use jar .You can remove tomcat dependency as well as spring boot will see spring web dependency and would provide embedded tomcat automatically. If your intention is to test only the controller behavior, then you should use spring boot test slices, in this case web slice. So you can annotate your test with @WebMvcTest Below is an excellent example and u should definitely check this out.

https://spring.io/guides/gs/testing-web/

Hope this helps

Thanks to chrylis and whysoseriousson . Now works

With these ideas, I have developed a new code (only Jar into pom.xml) and I have set the scope of "test dependency" to "test"

[...]
<packaging>war</packaging>
[...]
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

I had an aditional problem because the test file wasn't into the "test package". I have moved all the test files to "test package". It's curiosus that it worked into Neon Eclipse and not in last version

I knew the ( Test Tutorial of Spring ) and the most of ideas of my example are of this tutorial.

Thanks for the answer. Question closed

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM