如何使用 MockMvc 为 REST 控制器创建单元测试
How to create unit tests with MockMvc for your REST controller
我有一个 REST 控制器,我想为我的控制器创建 Unit tests
,但我对加载 spring 上下文不感兴趣。
有一个spring-boot应用程序,要求是使用junit5和MockMvc。
这是一个使用 MockMvc 的工作示例,为 REST 控制器创建简单的单元测试。
这是 Dictionary
REST 控制器。
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping(DICTIONARY_ENDPOINT_URL)
public class DictionaryController {
protected static final String DICTIONARY_ENDPOINT_URL = "/dictionaries";
private final DictionaryService dictionaryService;
@GetMapping(value = "download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<byte[]> downloadDictionariesFile() throws FileNotFoundException {
log.info("Called download dictionaries file endpoint.");
final String fileRelativePath = dictionaryService.getDictionariesFileRelativePath();
return ResponseEntity.ok()
.header("Content-Disposition", "attachment; filename=" + getDictionariesFileByRelativePath(fileRelativePath))
.body(dictionaryService.getDictionaryFileContent(fileRelativePath));
}
}
这是DictionaryControllerTest
package <...>;
import <...>.DictionaryService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.io.FileNotFoundException;
import static org.hamcrest.Matchers.containsString;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ExtendWith(MockitoExtension.class)
class DictionaryControllerTest {
private String dictionaryFilePath = "<<path to the file>>";
private String dictionaryFileContent = "<<content here>>";
private String errorMessage = "Dictionary file, does not exists!";
private String endpointUrl = "/dictionaries/download";
@Mock
private DictionaryService dictionaryService;
@InjectMocks
private DictionaryController dictionaryController;
private MockMvc mockMvc;
@BeforeEach
public void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(dictionaryController).build();
}
@Test
@DisplayName("Should return response with content file")
void downloadDictionariesFile_validRequest_success() throws Exception {
when(dictionaryService.getDictionariesFileRelativePath())
.thenReturn(dictionaryFilePath);
when(dictionaryService.getDictionaryFileContent(anyString()))
.thenReturn(dictionaryFileContent.getBytes());
mockMvc.perform(get(endpointUrl))
.andExpect(status().isOk())
.andExpect(content().string(containsString(dictionaryFileContent)));
verify(dictionaryService).getDictionariesFileRelativePath();
verify(dictionaryService).getDictionaryFileContent(any());
}
}
这是我的 pom.xml
文件的几行
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
我有一个 REST 控制器,我想为我的控制器创建 Unit tests
,但我对加载 spring 上下文不感兴趣。
有一个spring-boot应用程序,要求是使用junit5和MockMvc。
这是一个使用 MockMvc 的工作示例,为 REST 控制器创建简单的单元测试。
这是 Dictionary
REST 控制器。
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping(DICTIONARY_ENDPOINT_URL)
public class DictionaryController {
protected static final String DICTIONARY_ENDPOINT_URL = "/dictionaries";
private final DictionaryService dictionaryService;
@GetMapping(value = "download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<byte[]> downloadDictionariesFile() throws FileNotFoundException {
log.info("Called download dictionaries file endpoint.");
final String fileRelativePath = dictionaryService.getDictionariesFileRelativePath();
return ResponseEntity.ok()
.header("Content-Disposition", "attachment; filename=" + getDictionariesFileByRelativePath(fileRelativePath))
.body(dictionaryService.getDictionaryFileContent(fileRelativePath));
}
}
这是DictionaryControllerTest
package <...>;
import <...>.DictionaryService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.io.FileNotFoundException;
import static org.hamcrest.Matchers.containsString;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ExtendWith(MockitoExtension.class)
class DictionaryControllerTest {
private String dictionaryFilePath = "<<path to the file>>";
private String dictionaryFileContent = "<<content here>>";
private String errorMessage = "Dictionary file, does not exists!";
private String endpointUrl = "/dictionaries/download";
@Mock
private DictionaryService dictionaryService;
@InjectMocks
private DictionaryController dictionaryController;
private MockMvc mockMvc;
@BeforeEach
public void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(dictionaryController).build();
}
@Test
@DisplayName("Should return response with content file")
void downloadDictionariesFile_validRequest_success() throws Exception {
when(dictionaryService.getDictionariesFileRelativePath())
.thenReturn(dictionaryFilePath);
when(dictionaryService.getDictionaryFileContent(anyString()))
.thenReturn(dictionaryFileContent.getBytes());
mockMvc.perform(get(endpointUrl))
.andExpect(status().isOk())
.andExpect(content().string(containsString(dictionaryFileContent)));
verify(dictionaryService).getDictionariesFileRelativePath();
verify(dictionaryService).getDictionaryFileContent(any());
}
}
这是我的 pom.xml
文件的几行
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>