[JAVA] How to write a unit test for Spring Boot 2

Introduction

I decided to write a unit test with spring boot2, so I will organize the writing style.

How do you write a test of the value set in Model? I hope you can use it to remember in such cases.

Sample code is available on GitHub.

Response Status test


import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

this.mockMvc.perform(get("/")).andDo(print())
        //Whether to return the status "200 OK"
        .andExpect(status().isOk())
        .andExpect(status().is(200))

The documentation looks like here.

Both isOk () and is (200) give the same result.

thymeleaf template file

@Controller
@EnableAutoConfiguration
public class HomeController {
  @GetMapping(path = "/")
  String home(HttpServletRequest request, Model model) {
    // home.Specify html
    return "home";
  }
}

With that feeling, you will return the thymeleaf template file. This is a test.

    //test
    this.mockMvc.perform(get("/")).andDo(print())
        //Whether to return the template "home"
        .andExpect(view().name("home"))

Test with the name method. The documentation is here.

Model test

You pack data into the Model with the controller, right?

MyData.java


public class MyData {
  private String strData;
  private int intData;

  public MyData(String strData, int intData) {
    this.strData = strData;
    this.intData = intData;
  }

  public void setStrData(String strData) {
    this.strData = strData;
  }
  public String getStrData() {
    return this.strData;
  }

  public void setIntData(int intData) {
    this.intData = intData;
  }
  public int getIntData() {
    return this.intData;
  }
}

HomeController.java


@Controller
@EnableAutoConfiguration
public class HomeController {
  @GetMapping(path = "/")
  String home(HttpServletRequest request, Model model) {

    // string
    model.addAttribute("test", "this is test");

    // HashMap<String, String>
    HashMap<String, String> map = new HashMap<String, String>();
    map.put("name", "momotaro");
    map.put("age", "23");
    model.addAttribute("map", map);

    // List<String>
    List<String> list = new ArrayList<String>();
    list.add("list1");
    list.add("list2");
    list.add("list3");
    model.addAttribute("list", list);

    // List<MyData>
    List<MyData> list2 = new ArrayList<MyData>();
    list2.add(new MyData("test1", 111));
    list2.add(new MyData("test2", 222));
    model.addAttribute("list2", list2);

    // home.Specify html
    return "home";
  }
}

HomeControllerTest.java


@SpringBootTest(classes = HomeController.class)
@AutoConfigureMockMvc
public class HomeControllerTest {
  @Autowired
  private MockMvc mockMvc;

  @Test
void home screen() throws Exception {

    HashMap<String, String> map = new HashMap<String, String>();
    map.put("name", "momotaro");
    map.put("age", "23");

    List<String> list = new ArrayList<String>();
    list.add("list1");
    list.add("list2");
    list.add("list3");

    List<MyData> list2 = new ArrayList<MyData>();
    list2.add(new MyData("test1", 111));
    list2.add(new MyData("test2", 222));


    //test
    this.mockMvc.perform(get("/")).andDo(print())
        //Whether to return the status "200 OK"
        .andExpect(status().isOk())
        .andExpect(status().is(200))

        //Whether to return the template "home"
        .andExpect(view().name("home"))

        //Model test.

        //string type
        .andExpect(model().attribute("test", "this is test"))

        //HashMap type
        .andExpect(model().attribute("map", map))

        // List<String>Mold
        .andExpect(model().attribute("list", hasSize(3)))   //List size
        .andExpect(model().attribute("list", hasItem("list1")))   //Does list1 included
        .andExpect(model().attribute("list", hasItem("list2")))   //Does list2 included
        .andExpect(model().attribute("list", hasItem("list3")))   //Does list3 included
        .andExpect(model().attribute("list", contains("list1", "list2", "list3")))  // list1, list2,Is it included in the order of list3?
        .andExpect(model().attribute("list", is(list)))  //Whether it matches list

        // List<MyData>Mold
        .andExpect(model().attribute("list2", hasSize(2)))   //List size
        .andExpect(model().attribute("list2",
          hasItem(allOf(hasProperty("strData", is("test1")), hasProperty("intData", is(111))))
        ))   //Does this combination of data be included?
        .andExpect(model().attribute("list2",
          hasItem(allOf(hasProperty("strData", is("test2")), hasProperty("intData", is(222))))
        ))   //Does this combination of data be included?
        //.andExpect(model().attribute("list2", is(list2)))  //Whether it matches list2->This way of writing is not possible. An error will occur.

        ;
  }
}

You can test with the attribute method like this. The documentation is here

test redirect

It will be redirected by POST processing.

HomeController.java


  @PostMapping(path = "/testpost")
  public ModelAndView testpost(RedirectAttributes redirectAttributes,  @RequestParam(value = "intvalue", required = false, defaultValue = "0") Integer intvalue) {
    ModelAndView modelAndView = new ModelAndView("redirect:/testget");

    //Check input value
    if (intvalue <= 0) {
      redirectAttributes.addFlashAttribute("error", "intvalue must be greater than 0");
      return modelAndView;
    }
    //Set data
    modelAndView.addObject("value", intvalue);
    return modelAndView;
  }

HomeControllerTest.java


  @Test
  void testpost() throws Exception {
    //If you do not pass the parameter, it will be caught in the check
    this.mockMvc.perform(post("/testpost")).andExpect(redirectedUrl("/testget"))
        .andExpect(flash().attribute("error", "intvalue must be greater than 0"));

    //Pass the check after passing the parameters
    this.mockMvc.perform(post("/testpost").param("intvalue", "5"))
        .andExpect(redirectedUrl("/testget?value=5"));
  }

Use redirectedUrl () to test the redirected URL.

Use flash () to test redirectAttributes.addFlashAttribute ().

Parameters received by POST can be specified by param ().

Test if a particular method was called with a particular argument

When receiving POST on Controller I think I'll do something about it. That test.

Here, DI a specific Service to Controller Let's test that the Servcie method is called in the Post process.

MyService.java


@Service
public class MyService {
  public void test(int value) {
    System.out.println("MyService.test()..." + value);
  }
}

HomeController.java



@Controller
@EnableAutoConfiguration
public class HomeController {

  @Autowired
  MyService myService;

  @PostMapping(path = "/testpost2")
  public String testpost2(@RequestParam(value = "intvalue", required = false, defaultValue = "0") Integer intvalue) {

    //MyService test()Call
    myService.test(intvalue);

    return "redirect:/";
  }
}

HomeControllerTest.java


@SpringBootTest(classes = HomeController.class)
@AutoConfigureMockMvc
public class HomeControllerTest {
  @Autowired
  private MockMvc mockMvc;

  @MockBean
  private MyService myService;

  @Test
  void testpos2() throws Exception {
    //redirectUrl check
    this.mockMvc.perform(post("/testpost2").param("intvalue", "5")).andExpect(redirectedUrl("/"));

    //MyService test()Test if the method was called with an argument value of 5
    verify(this.myService, times(1)).test(5);
  }
}

verify(this.myService, times(1)).test(5);

If you write "The test method of the MyService class was called once with an argument value of 5" It will be a test.

The test to see if it was called twice

verify(this.myService, times(2)).test(5);

And

When you want the argument value to be 10

verify(this.myService, times(1)).test(10);

Write.

by this, The controller test Checking the value of the parameter to isolate the process, Passing parameter values to functions of other services I think it can be narrowed down to two types.

Test of Get parameters

Post parameters were specified in params (), The Get parameter is specified by the URL.

HomeController.java


  @GetMapping(path = "/testget")
  String testget(@RequestParam(value = "value", required = false, defaultValue = "0") Integer value, @ModelAttribute("error") String error, Model model) {

    model.addAttribute("strError", error);
    model.addAttribute("intValue", value);

    // testget.Specify html
    return "testget";
  }

HomeControllerTest.java


  @Test
  void testget() throws Exception {
    this.mockMvc.perform(get("/testget?value=5&error=SuperError")).andDo(print())
        //Whether to return the status "200 OK"
        .andExpect(status().isOk())

        //Whether to return the template "testget"
        .andExpect(view().name("testget"))

        //Model test.
        .andExpect(model().attribute("intValue", 5))
        .andExpect(model().attribute("strError", "SuperError"))
        ;
  }

in conclusion

It's still a memo when I started writing tests with spring boot, so I would like to continue to add more.

Sample code is available on GitHub.

end.

Recommended Posts

How to write a unit test for Spring Boot 2
How to unit test Spring AOP
[Spring Boot] How to create a project (for beginners)
I want to write a unit test!
[SpringBoot] How to write a controller test
How to make a hinadan for a Spring Boot project using SPRING INITIALIZR
Sample code to unit test a Spring Boot controller with MockMvc
Let's write a test code for login function in Spring Boot
How to add a classpath in Spring Boot
How to set Dependency Injection (DI) for Spring Boot
[JUnit 5 compatible] Write a test using JUnit 5 with Spring boot 2.2, 2.3
How to create a Spring Boot project in IntelliJ
[JUnit 5] Write a validation test with Spring Boot! [Parameterization test]
How to dynamically write iterative test cases using test / unit (Test :: Unit)
Write test code in Spring Boot
How to set Spring Boot + PostgreSQL
How to write a ternary operator
Use DBUnit for Spring Boot test
How to use ModelMapper (Spring boot)
[RSpec] How to write test code
How to test a private method with RSpec for yourself
Use Spring Test + Mockito + JUnit 4 for Spring Boot + Spring Retry unit tests
[Basic] How to write a Dockerfile Self-learning ②
[RSpec on Rails] How to write test code for beginners by beginners
[Introduction to Java] How to write a Java program
How to create a Maven repository for 2020
How to write Spring AOP pointcut specifier
How to write an RSpec controller test
How to split Spring Boot message file
[Rspec] Flow from introducing Rspec to writing unit test code for a model
How to not start Flyway when running unit tests in Spring Boot
Rails: How to write a rake task nicely
[Java] How to test for null with JUnit
About designing Spring Boot and unit test environment
How to create a database for H2 Database anywhere
[Rails] How to write when making a subquery
How to use MyBatis2 (iBatis) with Spring Boot 1.4 (Spring 4)
How to use built-in h2db with spring boot
How to make Spring Boot Docker Image smaller
JUnit 5: How to write test cases in enum
How to use Spring Boot session attributes (@SessionAttributes)
How to create pagination for a "kaminari" array
[Rails] How to implement unit tests for models
How to make a lightweight JRE for distribution
How to write test code with Basic authentication
How to bind to property file in Spring Boot
[Spring Boot] How to refer to the property file
Spring Boot --How to set session timeout time
How to write Rails
How to display characters entered in Spring Boot on a browser and reference links [Introduction to Spring Boot / For beginners]
How to write dockerfile
How to write docker-compose
How to write Mockito
How to write migrationfile
[Spring Boot] How to get properties dynamically from a string contained in a URL
How to perform UT with Excel as test data with Spring Boot + JUnit5 + DBUnit
Plans to support JDK 11 for Eclipse and Spring Boot
Settings for connecting to MySQL with Spring Boot + Spring JDBC
How to use an array for a TreeMap key
How to unit test with JVM with source using RxAndroid
A memorandum of addiction to Spring Boot2 x Doma2