How to use Mockito to call static methods and void methods
- 2021-10-25 06:51:50
- OfStack
1. mock static method
The mockito library is not an mock static method and relies on powermock
Step 1: Add annotations to classes
// Static classes are loaded first, so you need to tell them in advance powermock Which static classes require mock
@ContextConfiguration
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@PrepareForTest( Static calling class .class)
public class SupplierServiceImplTest extends PowerMockTestCase {}
Step 2: Using mock
@Test(expectedExceptions = BusinessException.class)
public void testAddSupplierAccount_genIdentityNoError() {
// Tell powermock , need mock All static methods of the class
PowerMockito.mockStatic(PasswordGenerator.class);
final SupplierAccountDto supplierAccountDto = new SupplierAccountDto();
supplierAccountDto.setName(" Xiao Ming ");
final String randomPWd = "666";
PowerMockito.when(supplierDao.selectByEmail(anyString()))
.thenReturn(new ArrayList<HaitaoSupplier>());
// Static method mock
PowerMockito.when(PasswordGenerator.genPwd()).thenReturn(randomPWd);
PowerMockito.when(pwEncoder.encode(anyString())).thenReturn(randomPWd);
PowerMockito.when(identityNoGenerator.genIdentityNo()).thenReturn(-1L);
supplierServiceImpl.addSupplierAccount(supplierAccountDto);
verify(pwEncoder).encode(randomPWd);
}
2. mock void method
// void Well, doNothing As the name implies
PowerMockito.doNothing().when(casService).addSupplier(anyLong(), any(ServiceKey.class));
Use PowerMockito and Mockito for simulation test
Include static method testing, private method testing, etc., and method execution pits or simulation unsuccessful resolution
1 General spring Project
Dependence: This is very important, and the usage of different versions is also somewhat different:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>2.0.2-beta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
Next is the mock test, which uses the complete simulation test process to return the expected results you want for the static and private methods that need to be called in the test interface to achieve the test effect:
Here are a few key points:
During the test, mock was completely manual, and no real call or data was generated
1 mock Object
order = mock(Order.class);
user = mock(User.class);
2 attribute injection
The other service, such as service or mapper, needed in the service and other mock, and then use the tool class injection respectively, and keep the name 1
roomTypeService = mock(RoomTypeServiceImpl.class);
ticketComponetService = mock(TicketComponetServiceImpl.class);
hotelMapper = mock(HotelMapper.class);
// Injection attribute
ReflectionTestUtils.setField(orderService, "hotelGroupMapper", hotelGroupMapper);
ReflectionTestUtils.setField(orderService, "dsUtils", dsUtils);
ReflectionTestUtils.setField(orderService, "orderMapper", orderMapper);
3 Static method mock
PowerMockit is required to simulate the results returned by static methods, and the test class must be annotated @ PrepareForTest
//account Get stub
PowerMockito.mockStatic(Account.class);
Mockito.when(Account.get(anyString(), anyString(), anyString(), anyInt())).thenReturn(account);
4 Private methods
Private methods need to be annotated on the class first, which is also effective for public methods in the class to be tested. For example, if the test method contains one public method, it can be simulated as well:
@PrepareForTest(ConsumptionServiceImpl.class) // It writes classes that need to simulate private methods class
Then the object cannot be mock, it must have new1, and it needs to be processed with spy:
orderService = PowerMockito.spy(new OrderServiceImpl());
Then use the formal mode of doreturn. when, but you can't use when before return, and you will report an error
Note 1: Simulation parameters are either all simulated or all customized, and cannot be mixed and matched
There is a big hole here. If there is a private method or go in to execute, it is very likely that the parameters are wrong. For example, the parameters of your mock are anyString (), then you must pass an String instance instead of null, otherwise mock will fail. I am here before 1 straight is an attribute of the object, and directly new passes an object
So 1 straight unsuccessful:
For example, the method needs user. getId (), and your mock is an anyInt (), so you must give this user and setId (9527) when you really pass it, otherwise you can't achieve the expected simulation effect, and all methods are one! !
try {<br> // Method name , Method parameter , Must all correspond , Otherwise, the error reporting method cannot be found
PowerMockito.doReturn(1).when(orderService, "dateListMinBook",anyString(),anyString(),any(RoomType.class),anyString(),anyString());
PowerMockito.doReturn(ResponseMessage.success().pushData("dateRoomTypeList",new ArrayList<DateRoomType>())).when(orderService, "eachDateNumAndPrice",any(Order.class),any(RoomType.class),anyBoolean(),anyInt(),anyString(),any(User.class));
PowerMockito.doReturn("2000").when(orderService, "getKeeptimeByWxcidAndHotelidAndLevel",anyString(),anyString(),anyString());
PowerMockito.doNothing().when(orderService, "getPayWay",any(),any(),any(),any(),any());
} catch (Exception e) {
e.printStackTrace();
}
5 Expected results
verify: Determine how many times the method was executed: Determine whether the test passed
For example: verify (userService, times (1)). queryUser (any (anyInt (), anyString (), anyString ());
2 springboot Project Use
1 Dependence
@Test(expectedExceptions = BusinessException.class)
public void testAddSupplierAccount_genIdentityNoError() {
// Tell powermock , need mock All static methods of the class
PowerMockito.mockStatic(PasswordGenerator.class);
final SupplierAccountDto supplierAccountDto = new SupplierAccountDto();
supplierAccountDto.setName(" Xiao Ming ");
final String randomPWd = "666";
PowerMockito.when(supplierDao.selectByEmail(anyString()))
.thenReturn(new ArrayList<HaitaoSupplier>());
// Static method mock
PowerMockito.when(PasswordGenerator.genPwd()).thenReturn(randomPWd);
PowerMockito.when(pwEncoder.encode(anyString())).thenReturn(randomPWd);
PowerMockito.when(identityNoGenerator.genIdentityNo()).thenReturn(-1L);
supplierServiceImpl.addSupplierAccount(supplierAccountDto);
verify(pwEncoder).encode(randomPWd);
}
0
2 Create a test base class
@Test(expectedExceptions = BusinessException.class)
public void testAddSupplierAccount_genIdentityNoError() {
// Tell powermock , need mock All static methods of the class
PowerMockito.mockStatic(PasswordGenerator.class);
final SupplierAccountDto supplierAccountDto = new SupplierAccountDto();
supplierAccountDto.setName(" Xiao Ming ");
final String randomPWd = "666";
PowerMockito.when(supplierDao.selectByEmail(anyString()))
.thenReturn(new ArrayList<HaitaoSupplier>());
// Static method mock
PowerMockito.when(PasswordGenerator.genPwd()).thenReturn(randomPWd);
PowerMockito.when(pwEncoder.encode(anyString())).thenReturn(randomPWd);
PowerMockito.when(identityNoGenerator.genIdentityNo()).thenReturn(-1L);
supplierServiceImpl.addSupplierAccount(supplierAccountDto);
verify(pwEncoder).encode(randomPWd);
}
1
3 Create a specific test class
@Test(expectedExceptions = BusinessException.class)
public void testAddSupplierAccount_genIdentityNoError() {
// Tell powermock , need mock All static methods of the class
PowerMockito.mockStatic(PasswordGenerator.class);
final SupplierAccountDto supplierAccountDto = new SupplierAccountDto();
supplierAccountDto.setName(" Xiao Ming ");
final String randomPWd = "666";
PowerMockito.when(supplierDao.selectByEmail(anyString()))
.thenReturn(new ArrayList<HaitaoSupplier>());
// Static method mock
PowerMockito.when(PasswordGenerator.genPwd()).thenReturn(randomPWd);
PowerMockito.when(pwEncoder.encode(anyString())).thenReturn(randomPWd);
PowerMockito.when(identityNoGenerator.genIdentityNo()).thenReturn(-1L);
supplierServiceImpl.addSupplierAccount(supplierAccountDto);
verify(pwEncoder).encode(randomPWd);
}
2
4 Simulate private and static methods
@PrepareForTest(OrderServiceImpl.class) // Classes that need to call private or static methods
public class OrderControllerTest extends TestBase {
private OrderServiceImpl orderServiceImpl; // When you need to call a private or static method , Can't be used @Mock, Need to @before Initialize properties
@Mock
private OrderMapper orderMapper;
@Mock
private RestTemplateUtil restTemplateUtil;
private Integer orderId;
private String wxcid;
@Before
public void init(){
// Handling private method simulation instances
orderServiceImpl = PowerMockito.spy(new OrderServiceImpl()); // Use spy Manual injection of attributes is required for simulation , Because there's nothing
ReflectionTestUtils.setField(orderController, "iOrderService", orderServiceImpl);
ReflectionTestUtils.setField(orderServiceImpl, "orderMapper", orderMapper);
ReflectionTestUtils.setField(orderServiceImpl, "restTemplateUtil", restTemplateUtil);
}
// Pure mock Test , Not loaded springContext, Execute mock Operation , Must mock Steps , Will not actually call
@InjectMocks
private OrderController orderController=new OrderController();
@Test
public void cancelTest(){
System.out.println("test start.....");
// 1 Structural parameter
ininParams();
// 2 mock Steps
mockStep();
// 3 Perform an operation
ResponseMessage cancel = orderController.cancel(wxcid, orderId);
assertEquals(0,(int)cancel.getCode());
}
private void mockStep() {
Order order = new Order();
order.setStatus(2);
when(orderMapper.getOrderByOrderId(anyInt())).thenReturn(order);
when(orderMapper.updateStatus(anyInt(),anyInt())).thenReturn(2);
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("code",0);
when(restTemplateUtil.postToCri(anyString(),anyString(),any())).thenReturn(jsonObject);
// Handling private methods , It must be written in this way
try {
PowerMockito.doNothing().when(orderServiceImpl, "returnTicketTouser", anyString(),any());
PowerMockito.doReturn(ErrorCode.SUCCESS).when(orderServiceImpl, "refoundAndGetCode", any(),any(),any(),any());
} catch (Exception e) {
e.printStackTrace();
}
}
private void ininParams() {
wxcid="57af462dff475fe4644de32f08406aa8";
orderId=25864;
}
}
Note:
If it is a sub-module project, there can only be one startup class in springboot project, that is, the startup annotations of other startup classes of service, dao and common modules need to be commented out, otherwise the test startup will report an error