catalogue
3, Common notes and methods of PowerMock
4, How to use PowerMock for unit testing?
1, What is Mock?
Mock is to create a mock object to simulate the behavior of some objects that are not easy to construct / obtain during the test. For example, if you need to call the B service, but the B service has not been developed yet, you can give the part of calling the B service to mock and write the return result you want.
Mock has many implementation frameworks, such as Mockito, EasyMock, Jmockit, PowerMock, Spock, etc. the default mock framework of SpringBoot is Mockito. Like junit, it only needs to rely on spring boot starter test.
2, Why use PowerMock?
Mockito framework does not support static # and mock of non-public methods or member variables. PowerMock extends EasyMock and mockito framework, adds the functions of mock static and Final methods, and realizes the simulation support of static methods, construction methods, private methods and Final methods.
3, Common notes and methods of PowerMock
- @Runwith(PowerMockRunner.class): Specifies the runner. To use powermock, you need to configure it. Otherwise, powermock cannot be used.
- @PrepareForTest({Util.class}): when you need to use the powerful functions of PowerMock (mock static, final, private methods, etc.), you need to annotate @ PrepareForTest annotation, util Class is the class of the static method that needs mock.
- @MockBean: create a mock object and add the mock object to the Spring context using the @ MockBean annotation.
- @AutoConfigureMockMvc: automatically configure mockmvc, which can be used to simulate HTTP requests.
- @AutoConfigureWebTestClient: AutoConfigureWebTestClient, like mockMvc, is used to simulate HTTP requests.
- @Mock: all calls to functions execute mock (i.e. false functions) and do not execute the real part.
- @Spy: calls to functions execute the real part.
- @InjectMocks: create an instance. In short, this Mock can call the methods of real code, and the other mocks created with @ Mock (or @ Spy) annotation will be injected into the instance.
4, How to use PowerMock for unit testing?
1. Introduce dependency
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.28.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>2.0.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>2.0.2</version> <scope>test</scope> </dependency>
2. Write BaseTest base class
// The rollback of configuration transaction and the addition, deletion and modification of database will be rolled back to facilitate the recycling of test cases @Rollback @Transactional @RunWith(PowerMockRunner.class) @PowerMockRunnerDelegate(SpringRunner.class) @PowerMockIgnore({"javax.management.*", "javax.net.ssl.*", "com.rabbitmq.*", "org.apache.log4j.*"}) @SpringBootTest public abstract class BaseTest { }
3. Basic usage of PowerMock
1) mock Http request
1,use MockMvc simulation Http request @AutoConfigureMockMvc public class DemoTest extends BaseTest { @Test void addUser() { User user = new User(1, "alien", "man", 12); try { mockMvc.perform(MockMvcRequestBuilders.post("/user/save") .contentType(MediaType.APPLICATION_JSON) .content(JSONObject.toJSONString(user))) // Declare expected response results .andExpect(MockMvcResultMatchers.status().isOk()) // Print response results .andDo(MockMvcResultHandlers.print()); } catch (Exception e) { e.printStackTrace(); } } } 2,use WebTestClient simulation Http request @AutoConfigureWebTestClient public class DemoTest extends BaseTest { @Test void findUserById() { User user = webClient.get() // Declare the request interface address, request parameters, request data flow type and request header .uri(uriBuilder -> uriBuilder.path("/user/id") .queryParam("id", 2).build()) .accept(MediaType.APPLICATION_JSON) .header("token", "123456") // Execute request .exchange() // Declare response status and header .expectStatus().isOk() .expectHeader().contentType(MediaType.APPLICATION_JSON) // Specifies how the response body is decoded and used .expectBody(User.class) // Obtain corresponding results .returnResult() .getResponseBody(); System.out.println(user.toString()); } }
2. mock common method
Test object code:
@Component public class StudentService { @Autowired private StudentDao studentDao; public String findStudents() { return studentDao.findStudents(); } } @Component public class StudentDao { public String findStudents() { return "i am dao data"; } }
Test case code:
public class DemoTest extends BaseTest { @MockBean private StudentDao studentDao; @Autowired private StudentService studentService; @Test public void test() { // mock | piling when(studentDao.findStudents()).thenReturn("i am mock data"); Assert.assertEquals("i am mock data", studentDao.findStudents()); // implement String s = studentService.findStudents(); // Use assertions to verify that the returned result is consistent with the expected value of mock Assert.assertEquals("i am mock data", s); } }
3. mock static method
Test object code:
@Component public class UserService { public String userStaticMethod() { String name = UserUtil.getName(); return name; } } public class UserUtil { public static String getName() { return "static-method: Bob"; } }
Test case code:
@PrepareForTest({UserUtil.class}) public class DemoTest extends BaseTest { @Autowired private UserService userService; @Test public void test() { // Pile driving PowerMockito.mockStatic(UserUtil.class); when(UserUtil.getName()).thenReturn("i am changed!"); // implement String s = userService.userStaticMethod(); // Use assertions to verify that the returned result is consistent with the expected value of mock Assert.assertEquals("i am changed!", s); } }
4. mock private method
Test object code:
@Component public class UserService { public String userPrivateMethod(String name) { return privateMethod(name); } private String privateMethod(String name) { return name; } }
Test case code:
PowerMockito.spy(): create simulated objects. If mock rules are not set, real methods will be executed. If mock rules are set, false methods will be executed.
PowerMockito.mock()/@MockBean: mock() or mock objects created by @ MockBean will always execute false methods. If mock rules are set, the false methods will return the expected value. If mock rules are not set, the methods will directly return null
@PrepareForTest({UserUtil.class,UserService.class}) public class DemoTest extends BaseTest { @Test public void test() { // Pile driving UserService spy = PowerMockito.spy(new UserService()); try { PowerMockito.when(spy, "privateMethod", anyString()).thenReturn("private method changed!!!"); } catch (Exception e) { e.printStackTrace(); } // implement String s = spy.userPrivateMethod("test"); // Use assertions to verify that the returned result is consistent with the expected value of mock Assert.assertEquals("private method changed!!!", s); } }