86427019 2020-06-07
今天整理了下,springboot下单元测试基本用法
若使用了 @RunWith(SpringRunner.class)配置,需要用 org.junit.Test运行,juint4包, junit5包org.junit.jupiter.api.Test 不需要RunWith注解.
一 引入依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>mvctest</artifactId> <version>0.0.1-SNAPSHOT</version> <name>mvctest</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <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> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
maven dependencies
二 接口代码
package com.example.mvctest.controller; import com.example.mvctest.dao.User; import com.example.mvctest.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * @Description TODO * @Author Administrator * @Email * @Date 2020/6/6 0006 下午 23:28 * @Version 1.0 */ @RestController public class UserController { @Autowired UserService userService; @GetMapping("/userList") public List<User> getUserList(){ return userService.findAll(); } @GetMapping("/user") public User getUser(Long id){ return userService.findById(id); } @PostMapping("/user") public User postUser(@RequestBody User user){ return userService.save(user); } }
controller code
package com.example.mvctest.service; import com.example.mvctest.dao.User; import com.example.mvctest.dao.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * @Description TODO * @Date 2020/6/7 0007 上午 11:04 * @Version 1.0 */ @Service public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; @Override public User findByName(String name) { return userRepository.findByName(name); } @Override public User findById(Long id) { return userRepository.findById(id).get(); } @Override public User save(User user) { return userRepository.save(user); } @Override public List<User> findAll() { return (List<User> )userRepository.findAll(); } }
service Code
@Setter @Getter @ToString @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private Integer age; private String address; public User() { } public User(String name, Integer age, String address) { this.name = name; this.age = age; this.address = address; } public User(Long id,String name, Integer age, String address) { this.id = id; this.name = name; this.age = age; this.address = address; } }
entity Code
@Repository public interface UserRepository extends PagingAndSortingRepository<User,Long> { User findByName(String name); }
dao Code
二 dao单层测试
package com.example.mvctest.autoconfigtest; import com.example.mvctest.dao.User; import com.example.mvctest.dao.UserRepository; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; import static org.assertj.core.api.Assertions.assertThat; @DataJpaTest public class AutoConfigureDataJpaTest { @Autowired private TestEntityManager entityManager; @Autowired private UserRepository userRepository; @Test public void dao_user_test(){ User user = new User("leo",5,"合肥"); entityManager.persist(user); entityManager.flush(); User byName = userRepository.findByName(user.getName()); assertThat(byName.getName()).isEqualTo(user.getName()); } }
三 service单层测试
package com.example.mvctest.autoconfigtest; import com.example.mvctest.dao.User; import com.example.mvctest.dao.UserRepository; import com.example.mvctest.service.UserService; import com.example.mvctest.service.UserServiceImpl; import org.assertj.core.api.Assertions; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Bean; import org.springframework.test.context.junit4.SpringRunner; import java.util.Optional; import static org.mockito.Mockito.when; @RunWith(SpringRunner.class) public class ServiceLayerTest { @TestConfiguration static class ServiceTestConfiguer{ @Bean public UserService userService(){ return new UserServiceImpl(); } } @Autowired UserService userService; @MockBean UserRepository userRepository; @Test public void user_service_mock_dao_test(){ User user = new User(1L,"tim",3,"hubei"); when(userRepository.findById(user.getId())).thenReturn(Optional.of(user)); Assertions.assertThat(userService.findById(1L).getId()).isEqualTo(1L); } }
四 controller单层测试
package com.example.mvctest.autoconfigtest; import com.example.mvctest.controller.UserController; import com.example.mvctest.dao.User; import com.example.mvctest.service.UserService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import java.util.ArrayList; import java.util.List; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.mockito.BDDMockito.given; 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.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** * @Description @WebMvcTest注解:只扫描有限类型的bead来测试,只测试控制层的逻辑,service层数据通过 mock处理, * (limit scanned beans to @Controller, @ControllerAdvice, @JsonComponent, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver. * Regular @Component beans will not be scanned when using this annotation) * @Date 2020/6/7 0007 下午 15:57 * @Version 1.0 */ @WebMvcTest(UserController.class) public class AutoConfigureMvcTest { @Autowired private MockMvc mvc; @MockBean UserService userService; @Test public void mvc_user_test() throws Exception { List<User> userList = new ArrayList<>(2); userList.add(new User(1L,"john",3,"beijing")); userList.add(new User(2L,"jay",4,"shanghai")); given(userService.findAll()).willReturn(userList); this.mvc.perform(get("/userList").accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andDo(print()) .andExpect(jsonPath("$",hasSize(2))) .andExpect(jsonPath("$[0].id",is(1))); } }
五 mvc接口测试
package com.example.mvctest.autoconfigtest; import com.example.mvctest.MyApplication; import com.example.mvctest.dao.User; import com.example.mvctest.service.UserService; import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.Test; 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.http.MediaType; import org.springframework.test.context.TestPropertySource; import org.springframework.test.web.servlet.MockMvc; 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.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = MyApplication.class) @AutoConfigureMockMvc @TestPropertySource(locations = "classpath:application-integrationtest.properties") public class ApplicationTest { @Autowired private MockMvc mockMvc; @Autowired UserService userService; @Test public void web_user_get_test() throws Exception{ createTestUser(); this.mockMvc.perform(get("/user?id=1").contentType(MediaType.APPLICATION_JSON)).andDo(print()) .andExpect(status().isOk()) .andExpect(content() .contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.id", CoreMatchers.is(1))); } void createTestUser(){ User user =new User(); user.setId(1L); userService.save(user); } }
六 json 格式测试
package com.example.mvctest.autoconfigtest; import com.example.mvctest.dao.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.json.JsonTest; import org.springframework.boot.test.json.JacksonTester; import static org.assertj.core.api.Assertions.assertThat; @JsonTest public class AutoConfigureJsonTest { @Autowired private JacksonTester<User> json; @Test public void testSerialize() throws Exception { User details = new User("Honda",8, "Civic"); // Or use JSON path based assertions assertThat(this.json.write(details)) .hasJsonPathStringValue("@.name"); assertThat(this.json.write(details)) .extractingJsonPathStringValue("@.name") .isEqualTo("Honda"); // Assert against a `.json` file in the same package as the test // assertThat(this.json.write(details)).isEqualToJson("expected.json"); } @Test public void testDeserialize() throws Exception { String content = "{\"id\":1,\"name\":\"Ford\",\"age\":8,\"address\":\"Focus\"}"; // assertThat(this.json.parse(content)).isEqualTo(new User(1L,"Ford",8, "Focus")); assertThat(this.json.parseObject(content).getName()).isEqualTo("Ford"); } }
七 http请求测试
package com.example.mvctest; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.web.server.LocalServerPort; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class HttpRequestTest { @LocalServerPort private int port; @Autowired private TestRestTemplate restTemplate; @Test public void greetingShouldReturnDefaultMessage() throws Exception { assertThat(this.restTemplate.getForObject("http://localhost:" + port + "/", String.class)).contains("Hello, World"); } }
七 参考文档
https://spring.io/guides/gs/testing-web/
https://www.baeldung.com/spring-boot-testing
https://docs.spring.io/spring-boot/docs/1.5.7.RELEASE/reference/html/boot-features-testing.html
后期继续补充使用,初步整理使用记录,继续提升单元测试覆盖率,结合阿里java开发规约中单元测试相关内容理解使用.
测试代码连接: https://github.com/wangrqsh/mvctest_learn.git