[JAVA] I wrote a test with Spring Boot + JUnit 5 now

Introduction

When I got used to JUnit4 too much and decided to write in JUnit5, I had to investigate quite a bit. Now, I will summarize the frequently used implementation samples for myself.

In addition, the Web application to be tested assumes Rest API and does not include the View layer test.

Implementation sample covered in this article

--Controller test Make a pseudo request with MockMVC and test Filter + Controller + ExceptionHandler

--Testing with Mock --Mock the bean and test it --Mock one to DI and the other to Mock for testing

--Parameterization test Repeat the same case with only the test data changed

Development environment

1. Preparing the application to be tested

First, create an app to be tested. As usual, Created by adding lombok, Spring Web, Validation to dependencies in GradleProject with spring initializr .RELEASE&packaging=jar&jvmVersion=11&groupId=com.example&artifactId=demo&name=demo&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.demo&dependencies=lombok,web,validation).

build.gradle


plugins {
	id 'org.springframework.boot' version '2.3.4.RELEASE'
	id 'io.spring.dependency-management' version '1.0.10.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-validation'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation('org.springframework.boot:spring-boot-starter-test') {
		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
	testCompileOnly 'org.projectlombok:lombok'  //add to
	testAnnotationProcessor 'org.projectlombok:lombok'  //add to
}

test {
	useJUnitPlatform()
}

For the generated build.gradle, two lines have been added to dependency so that lombok can be used in the test code. (See comments above) We will create the following classes for this project.

1-1. Creating Service and Configuration

Create two Services called from Controller. First of all, it performs simple internal processing.

DemoService.java


@Service
public class DemoService {
  //I'll say hello
  public String hello() {
    return "hello";
  }
  //I'll divide
  public BigDecimal divide(BigDecimal a, BigDecimal b) {
    return a.divide(b, 2, RoundingMode.HALF_UP);
  }
}

The other is to get an external resource (Qiita API).

ExternalService.java


@Service
@RequiredArgsConstructor
public class ExternalService {
  private static final String EXTERNAL_RESOURCE_URL = "https://qiita.com/api/v2/schema";
  private final RestTemplate restTemplate;
  //Returns the result of Schema of Qiita API
  public String getExternalResource() {
    ResponseEntity<String> response =
        restTemplate.exchange(EXTERNAL_RESOURCE_URL, HttpMethod.GET, null, String.class);
    return response.getBody();
  }
}

Create a Configuration class to DI the above restTemplate.

AppConfig.java


@Configuration
public class AppConfig {
  @Bean
  public RestTemplate restTemplate() {
    return new RestTemplate();
  }
}

1-2. Creating a Controller

Create a Controller that uses the two Services mentioned earlier.

DemoController.java


@RestController
@RequiredArgsConstructor
@Validated
public class DemoController {

  private final DemoService demoService;
  private final ExternalService externalService;

  //I'll say hello
  @GetMapping("/")
  public CommonResponse hello() {
    String data = demoService.hello();
    return CommonResponse.builder().data(data).build();
  }

  //I'll divide
  @GetMapping("/divide/{num1}/{num2}")
  public CommonResponse divide(
      @PathVariable @Pattern(regexp = "[0-9]*") String num1,
      @PathVariable @Pattern(regexp = "[0-9]*") String num2) {
    BigDecimal data = demoService.divide(new BigDecimal(num1), new BigDecimal(num2));
    return CommonResponse.builder().data(data).build();
  }

  //Returns the result of Schema of Qiita API
  @GetMapping("/external")
  public CommonResponse external() {
    String data = externalService.getExternalResource();
    return CommonResponse.builder().data(data).build();
  }
}

Since the division is checking the input, we will implement the test case later from this point of view. Create the response class as follows.

CommonResponse.java


@Data
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CommonResponse<T> {
    @Builder.Default
    private String status = "success";
    @Builder.Default
    private String message = "request succeeded.";
    private T data;
}

1-3. Creating Filter and ExceptionHandler

We will also create a Filter and an ExceptionHandler for a more practical sample. This filter is as simple as outputting a log before and after processing a request.

LogFilter.java


@Component
@Slf4j
public class LogFilter implements Filter {
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    log.info("[IN]{}:{}", req.getMethod(), req.getRequestURI());
    try {
      chain.doFilter(request, response);
    } finally {
      log.info("[OUT]{}:{}", req.getMethod(), req.getRequestURI());
    }
  }
}

Also create an ExceptionHandler. It is used to handle various errors in common.

CommonExceptionHandler.java


@RestControllerAdvice
@Slf4j
public class CommonExceptionHandler extends ResponseEntityExceptionHandler {

  // 404:Handles Resource Not Found errors
  //* To handle this application.You also need to set properties
  @Override
  protected ResponseEntity handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
    ServletWebRequest req = (ServletWebRequest)request;
    log.warn("resource not found. {}", req.getRequest().getRequestURI());
    return new ResponseEntity(
            CommonResponse.builder().status("failure").message("resource not found.").build(),
            HttpStatus.NOT_FOUND);
  }

  // 400:Handles input check errors
  @ExceptionHandler(ConstraintViolationException.class)
  public ResponseEntity<CommonResponse> handleValidationError(ConstraintViolationException e) {
    //Separate input error items and messages with commas(,)Added to.
    String validationErrorMessages =
        e.getConstraintViolations().stream()
            .map(cv -> cv.getPropertyPath().toString() + ":" + cv.getMessage())
            .collect(Collectors.joining(", "));
    log.info("Bad request. {}", validationErrorMessages);
    return new ResponseEntity<>(
        CommonResponse.builder().status("failure").message(validationErrorMessages).build(),
        HttpStatus.BAD_REQUEST);
  }

  // 500:Handles other unknown errors
  @ExceptionHandler
  public ResponseEntity<CommonResponse> handleException(Exception e) {
    log.error("Request failed.", e);
    return new ResponseEntity<>(
        CommonResponse.builder().status("failure").message("error has occurred.").build(),
        HttpStatus.INTERNAL_SERVER_ERROR);
  }
}

Put the following settings in ʻapplication.properties to handle 404: Resouce Not Found` in the above ExceptionHandler.

application.properties


spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

1-4. Structure of created file

This completes the preparation of the application to be used for testing. The files edited and created up to this point have the following structure.

├── build.gradle
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com.example.demo
│   │   │               ├── AppConfig.java
│   │   │               ├── DemoApplication.java
│   │   │               ├── controller
│   │   │               │   ├── CommonExceptionHandler.java
│   │   │               │   ├── CommonResponse.java
│   │   │               │   └── DemoController.java
│   │   │               ├── filter
│   │   │               │   └── LogFilter.java
│   │   │               └── service
│   │   │                   ├── DemoService.java
│   │   │                   └── ExternalService.java
│   │   └── resources
│   │       └── application.properties
│   └── test
└── web

2. Controller test

The main roles of Controller are as follows.

--Request mapping --Getting parameters

Since these behaviors depend on the functionality of Spring MVC, it doesn't make much sense to write test code for the Controller class alone. Therefore, we will use MockMVC to perform a test that reproduces the behavior of Spring MVC.

2-1. Sample test case using MockMVC

Regarding the request accepted by the Controller, not only the normal case but also the response of the assumed abnormal case such as an input check error is verified without exception.

DemoControllerTest.java


package com.example.demo.controller;

import com.example.demo.filter.LogFilter;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@EnableWebMvc
@Slf4j
public class DemoControllerTest {

  MockMvc mockMvc;

  @Autowired WebApplicationContext webApplicationContext;
  @Autowired LogFilter logFilter;

  @BeforeEach
  void beforeEach() {
    mockMvc =
        MockMvcBuilders.webAppContextSetup(webApplicationContext)     //Set up Mock MVC
            .addFilter(logFilter, "/*")                               //However, filter needs to be added manually
            .build();
  }

  //root"/I'll test your request
  @Test
  void hello() throws Exception {
    mockMvc.perform(get("/"))                                         //root"/Send a pseudo request to
        .andExpect(status().isOk())                                   //HttpStatus is 200:Be OK
        .andExpect(jsonPath("$.status").value("success"))             //The value of json is as expected
        .andExpect(jsonPath("$.message").value("request succeeded.")) // 〃
        .andExpect(jsonPath("$.data").value("hello"));
  }

  //I'll test the division (10/3) request
  @Test
  void divideSuccess() throws Exception { 
    mockMvc
        .perform(get("/divide/10/3"))                                 // 「/divide/10/Send pseudo request to 3 "
        .andExpect(status().isOk())                                   //HttpStatus is 200:Be OK
        .andExpect(jsonPath("$.status").value("success"))
        .andExpect(jsonPath("$.message").value("request succeeded."))
        .andExpect(jsonPath("$.data").value("3.33"));                 // 10 ÷ 3 = 3.Be 33
  }
  
  //Test for bad requests (10 ÷ aaa)
  @Test
  void divideInvalidParameter() throws Exception {
    mockMvc
        .perform(get("/divide/10/aaa"))                               // 「/divide/10/Send pseudo request to aaa "
        .andExpect(status().isBadRequest())                           //HttpStatus is 400:Being a BadRequest
        .andExpect(jsonPath("$.status").value("failure"))
        .andExpect(jsonPath("$.message").value("divide.num2:must match \"[0-9]*\"")); //There is an error message
  }

  //I'll test a request for division by zero (10 ÷ 0)
  @Test
  void divideZeroError() throws Exception {
    mockMvc
        .perform(get("/divide/10/0"))                                   // 「/divide/10/Send pseudo request to "0"
        .andExpect(status().is5xxServerError())                         //HttpStatus is 500:ServerError
        .andExpect(jsonPath("$.status").value("failure"))
        .andExpect(jsonPath("$.message").value("error has occurred."));
  }
  
  //Test the acquisition of external resources (Qiita schema API)
  @Test
  void getExternalResource() throws Exception {
    MvcResult mvcResult =
        mockMvc
            .perform(get("/external"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.status").value("success"))
            .andExpect(jsonPath("$.message").value("request succeeded."))
            .andExpect(jsonPath("$.data").isNotEmpty())                //Not empty
            .andReturn();
    //I will output the acquired response to the log
    log.info("external response : {}", mvcResult.getResponse().getContentAsString());
  }
}

The point is to set up MockMvc with WebAppicationContext. [^ 1] By doing this, it reproduces almost the same state as deploying to the application server.

[^ 1]: MockMvc also has another standalone setup, and there is also a mode suitable for unit tests that can be finely customized such as Controller, ControllerAdvice, Config to be tested.

** However, note that only Filter needs to be specified by ʻaddFilter (Filter," path ")`. ** **

3. Testing with Mock

The previous test used DI Controller and Service.

However, when using an external resource such as ʻExternalService`, it is not good for the controller test to fail due to the state (the other server is down and inaccessible, Wi-Fi is turned off, etc.). ..

** Use Mock at such times. ** **

3-1. Mock the bean and test it

If you check the role of Controller again,

  1. Request mapping
  2. Get parameters
  3. Input check
  4. Calling business logic (Service)
  5. Return of response

However, of these, 4. Calling Business Logic (Service) can be ** mocked to return the expected value so that you can focus on testing the Controller **.

Let's make the Service class of the previous test into a Mock.

DemoControllerWithMockTest.java


package com.example.demo.controller;

import com.example.demo.filter.LogFilter;
import com.example.demo.service.DemoService;
import com.example.demo.service.ExternalService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import java.math.BigDecimal;

import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@EnableWebMvc
@Slf4j
class DemoControllerWithMockTest {

  MockMvc mockMvc;

  @Autowired WebApplicationContext webApplicationContext;
  @Autowired LogFilter logFilter;

  @MockBean DemoService demoService;         //Convert to Mock and register in DI container
  @MockBean ExternalService externalService; // 〃

  @BeforeEach
  void beforeEach() {
    MockitoAnnotations.initMocks(this);
    mockMvc =
        MockMvcBuilders.webAppContextSetup(webApplicationContext)
            .addFilter(logFilter, "/*")
            .build();
  }

  @AfterEach
  void afterEach() {}

  @Test
  void hello() throws Exception {
    // mock
    when(demoService.hello()).thenReturn("Hello");      //First set the return value of the mock
    // request execute
    mockMvc
        .perform(get("/"))
        .andExpect(status().isOk())
        .andExpect(jsonPath("$.status").value("success"))
        .andExpect(jsonPath("$.message").value("request succeeded."))
        .andExpect(jsonPath("$.data").value("Hello"));  //Verify by changing the expected value
    // verify
    verify(demoService, times(1)).hello();                 //Verify the number of mock calls
  }

  @Test
  void divideSuccess() throws Exception {
    // mock
    when(demoService.divide(any(), any())).thenReturn(new BigDecimal("3.33")); //Regardless of the argument"3.33"return it
    // request execute
    mockMvc
        .perform(get("/divide/10/3"))
        .andExpect(status().isOk())
        .andExpect(jsonPath("$.status").value("success"))
        .andExpect(jsonPath("$.message").value("request succeeded."))
        .andExpect(jsonPath("$.data").value("3.33"));
    // verify
    verify(demoService, times(1)).divide(any(), any());
  }

  @Test
  void divideInvalidParameter() throws Exception {
    // request execute
    mockMvc
        .perform(get("/divide/10/aaa"))
        .andExpect(status().isBadRequest())
        .andExpect(jsonPath("$.status").value("failure"))
        .andExpect(jsonPath("$.message").value("divide.num2:must match \"[0-9]*\""));
    // verify
    verify(demoService, times(0)).divide(any(), any());  //Mock call validated 0 times due to input error
  }

  @Test
  void divideZeroError() throws Exception {
    // mock
    when(demoService.divide(any(), eq(BigDecimal.ZERO)))
        .thenThrow(new ArithmeticException("/ by zero"));              //Reproduce the error assuming division by zero
    // request execute
    mockMvc
        .perform(get("/divide/10/0"))
        .andExpect(status().is5xxServerError())
        .andExpect(jsonPath("$.status").value("failure"))
        .andExpect(jsonPath("$.message").value("error has occurred."));
    // verify
    verify(demoService, times(1)).divide(any(), eq(BigDecimal.ZERO));  //Mock call validates once
  }

  @Test
  void getExternalResource() throws Exception {
    // mock
    when(externalService.getExternalResource())
        .thenReturn("this is mock data for internal test.");    //Return wording without accessing external resources
    // request execute
    MvcResult mvcResult =
        mockMvc
            .perform(get("/external"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.status").value("success"))
            .andExpect(jsonPath("$.message").value("request succeeded."))
            .andExpect(jsonPath("$.data").value("this is mock data for internal test."))
            .andReturn();
    //I will output the acquired response to the log
    log.info("external response : {}", mvcResult.getResponse().getContentAsString());
    // verify
    verify(externalService, times(1)).getExternalResource();  //Mock call validates once
  }
}

Most importantly with this change is that ʻExternalService` now returns mock data without accessing external resources.

You can now run Controller tests independently of external resources.

3-2. Test one with DI and the other with Mock

In the previous test, both DemoService and ʻExternalService were Mocked, but ** only one can be Mocked **. For example, if you want to Mock only ʻExternalService, it will be as follows.

DemoControllerWithOneSideMockTest.java


package com.example.demo.controller;

import com.example.demo.filter.LogFilter;
import com.example.demo.service.ExternalService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@EnableWebMvc
@Slf4j
class DemoControllerWithOneSideMockTest {

  MockMvc mockMvc;

  @Autowired WebApplicationContext webApplicationContext;
  @Autowired LogFilter logFilter;

  @MockBean ExternalService externalService;    //External Service has external access, so make it a Mock

  @BeforeEach
  void beforeEach() {
    MockitoAnnotations.initMocks(this);
    mockMvc =
        MockMvcBuilders.webAppContextSetup(webApplicationContext)
            .addFilter(logFilter, "/*")
            .build();
  }

  @AfterEach
  void afterEach() {}

  @Test
  void hello() throws Exception {
    mockMvc
        .perform(get("/"))
        .andExpect(status().isOk())
        .andExpect(jsonPath("$.status").value("success"))
        .andExpect(jsonPath("$.message").value("request succeeded."))
        .andExpect(jsonPath("$.data").value("hello"));
  }

  @Test
  void divideSuccess() throws Exception {
    mockMvc
        .perform(get("/divide/10/3"))
        .andExpect(status().isOk())
        .andExpect(jsonPath("$.status").value("success"))
        .andExpect(jsonPath("$.message").value("request succeeded."))
        .andExpect(jsonPath("$.data").value("3.33"));
  }

  @Test
  void divideInvalidParameter() throws Exception {
    mockMvc
        .perform(get("/divide/10/aaa"))
        .andExpect(status().isBadRequest())
        .andExpect(jsonPath("$.status").value("failure"))
        .andExpect(jsonPath("$.message").value("divide.num2:must match \"[0-9]*\""));
  }

  @Test
  void divideZeroError() throws Exception {
    mockMvc
        .perform(get("/divide/10/0"))
        .andExpect(status().is5xxServerError())
        .andExpect(jsonPath("$.status").value("failure"))
        .andExpect(jsonPath("$.message").value("error has occurred."));
  }

  //Only the acquisition of external resources is verified using Mock.
  @Test
  void getExternalResource() throws Exception {
    // mock
    when(externalService.getExternalResource()).thenReturn("this is mock data for internal test.");
    // request
    MvcResult mvcResult =
        mockMvc
            .perform(get("/external"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.status").value("success"))
            .andExpect(jsonPath("$.message").value("request succeeded."))
            .andExpect(jsonPath("$.data").value("this is mock data for internal test."))
            .andReturn();
    //
    log.info("external response : {}", mvcResult.getResponse().getContentAsString());
    // verify
    verify(externalService, times(1)).getExternalResource();
  }
}

With this, you can freely DI the bean at the time of testing or mock it. Very convenient! !!

4. Parameterization test

Finally, I will leave a sample of the convenience function parameterization test added in JUnit5 by taking the unit test of Service as an example. It will be easy to repeat the same case by changing only the test data.

DemoServiceTest.java


package com.example.demo.service;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
class DemoServiceTest {

  @Autowired DemoService demoService;

  @Test
  void hello() {
    assertEquals("hello", demoService.hello());
  }

  // @Test the division method with various input patterns with ParameterizedTest
  @ParameterizedTest
  @MethodSource("divideTestArgs")  // "devideTestArgs"I'll use a static method named as the argument source
  void divide(String b1, String b2, String strExpect, boolean hasError) {

    BigDecimal expect = Optional.ofNullable(strExpect).map(BigDecimal::new).orElse(null);
    BigDecimal actual = null;
    Exception error = null;
    //Division method execution
    try {
      actual = demoService.divide(new BigDecimal(b1), new BigDecimal(b2));
    } catch (Exception e) {
      error = e;
    }
    //Expected value and verification
    assertEquals(expect, actual);
    //Verify that no error has occurred
    assertEquals(hasError, error != null);
  }

  //divide test parameter list
  static List<Object[]> divideTestArgs() {
    return List.of(
        new Object[] {"1", "1", "1.00", false},
        new Object[] {"0", "1", "0.00", false},
        new Object[] {"5", "2", "2.50", false},
        new Object[] {"10", "3", "3.33", false}, //Rounding (rounding down to the third decimal place)
        new Object[] {"11", "3", "3.67", false}, //Rounding (rounding up to the third decimal place)
        new Object[] {"1", "0", null, true}); //Division by zero
  }
}

Besides, MethodSource

It seems that you can use such as as a data source.

About the function of JUnit5 [this page](https://qiita.com/opengl-8080/items/efe54204e25f615e322f#%E3%83%91%E3%83%A9%E3%83%A1%E3%83% BC% E3% 82% BF% E5% 8C% 96% E3% 83% 86% E3% 82% B9% E3% 83% 88) was very easy to understand! I was very helpful mm

Afterword

There are many articles about testing JUnit, but there are also quite a few articles from older versions, so I hope it will be helpful for beginners who are challenging from Spring Boot and JUnit 5.

Recommended Posts

I wrote a test with Spring Boot + JUnit 5 now
[JUnit 5 compatible] Write a test using JUnit 5 with Spring boot 2.2, 2.3
I tried GraphQL with Spring Boot
I tried Flyway with Spring Boot
Test Spring framework controller with Junit
I wrote a CRUD test with SpringBoot + MyBatis + DBUnit (Part 1)
Create a parent-child relationship form with form_object (I also wrote a test)
Perform transaction confirmation test with Spring Boot
I made a simple search form with Spring Boot + GitHub Search API.
Sample code to unit test a Spring Boot controller with MockMvc
I tried Lazy Initialization with Spring Boot 2.2.0
Form class validation test with Spring Boot
[Spring Boot] I stumbled upon a method call count test (Spock framework)
[LINE BOT] I made a ramen BOT with Java (Maven) + Heroku + Spring Boot (1)
Create a website with Spring Boot + Gradle (jdk1.8.x)
Test controller with Mock MVC in Spring Boot
Create a simple search app with Spring Boot
I wrote a primality test program in Java
[Java] Hello World with Java 14 x Spring Boot 2.3 x JUnit 5 ~
I wanted to gradle spring boot with multi-project
Create a web api server with spring boot
Create a Spring Boot development environment with docker
Unit test with Junit.
Download with Spring Boot
How to perform UT with Excel as test data with Spring Boot + JUnit5 + DBUnit
I tried to clone a web application full of bugs with Spring Boot
[RSpec] I wrote a test for uploading a profile image.
How to write a unit test for Spring Boot 2
Implement a simple Rest API with Spring Security with Spring Boot 2.0
A memorandum when creating a REST service with Spring Boot
Create a simple demo site with Spring Security with Spring Boot 2.1
What I was addicted to when developing a Spring Boot application with VS Code
I wrote a test code (Junit & mockit) for the code that calls the AWS API (Java)
A memo that I was addicted to when making batch processing with Spring Boot
Generate barcode with Spring Boot
Hello World with Spring Boot
Test Web API with junit
Get started with Spring boot
Hello World with Spring Boot!
Run LIFF with Spring Boot
SNS login with Spring Boot
Spring Boot starting with Docker
Hello World with Spring Boot
Set cookies with Spring Boot
Use Spring JDBC with Spring Boot
Add module with Spring Boot
Getting Started with Spring Boot
Create microservices with Spring Boot
Send email with spring boot
Spring Boot Introductory Guide I tried [Accessing Data with JPA]
A story packed with the basics of Spring Boot (solved)
Let's make a simple API with EC2 + RDS + Spring boot ①
I investigated Randoop, a JUnit test class generator for Java
I tried to get started with Swagger using Spring Boot
Implement a simple Rest API with Spring Security & JWT with Spring Boot 2.0
Use Spring Test + Mockito + JUnit 4 for Spring Boot + Spring Retry unit tests
I made a simple MVC sample system using Spring Boot
[Java] I want to test standard input & standard output with JUnit
Implement a simple Web REST API server with Spring Boot + MySQL
I tried Spring Boot introductory guide [Building a RESTful Web Service]
Use Basic Authentication with Spring Boot