今天整理了下,springboot下單元測試基本用法 若使用了 @RunWith(SpringRunner.class)配置,需要用 org.junit.Test運行,juint4包, junit5包org.junit.jupiter.api.Test 不需要RunWith註解. 一 引入依賴 1 ...
今天整理了下,springboot下單元測試基本用法
若使用了 @RunWith(SpringRunner.class)配置,需要用 org.junit.Test運行,juint4包, junit5包org.junit.jupiter.api.Test 不需要RunWith註解.
一 引入依賴
1 <parent> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-parent</artifactId> 4 <version>2.3.0.RELEASE</version> 5 <relativePath/> <!-- lookup parent from repository --> 6 </parent> 7 <groupId>com.example</groupId> 8 <artifactId>mvctest</artifactId> 9 <version>0.0.1-SNAPSHOT</version> 10 <name>mvctest</name> 11 <description>Demo project for Spring Boot</description> 12 13 <properties> 14 <java.version>1.8</java.version> 15 </properties> 16 17 <dependencies> 18 <dependency> 19 <groupId>org.springframework.boot</groupId> 20 <artifactId>spring-boot-starter-web</artifactId> 21 </dependency> 22 23 <dependency> 24 <groupId>com.h2database</groupId> 25 <artifactId>h2</artifactId> 26 <scope>runtime</scope> 27 </dependency> 28 <dependency> 29 <groupId>org.springframework.boot</groupId> 30 <artifactId>spring-boot-starter-data-jpa</artifactId> 31 </dependency> 32 <dependency> 33 <groupId>org.projectlombok</groupId> 34 <artifactId>lombok</artifactId> 35 <optional>true</optional> 36 </dependency> 37 <dependency> 38 <groupId>org.springframework.boot</groupId> 39 <artifactId>spring-boot-starter-test</artifactId> 40 <scope>test</scope> 41 <exclusions> 42 <exclusion> 43 <groupId>org.junit.vintage</groupId> 44 <artifactId>junit-vintage-engine</artifactId> 45 </exclusion> 46 </exclusions> 47 </dependency> 48 <dependency> 49 <groupId>junit</groupId> 50 <artifactId>junit</artifactId> 51 <scope>test</scope> 52 </dependency> 53 </dependencies> 54 55 <build> 56 <plugins> 57 <plugin> 58 <groupId>org.springframework.boot</groupId> 59 <artifactId>spring-boot-maven-plugin</artifactId> 60 </plugin> 61 </plugins> 62 </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 [email protected] * @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