Use PowerMock to write Java UT.
Pom files introduce dependencies
<! -- PowerMock JUnit4.4+ Module --> <dependency> <groupId>org. powerMock </groupId> <artifactId>powermock-module-junit4</artifactId> <version>2.0. 0</version> <scope>test</scope> </dependency> <! --> <dependency> <groupId>org. PowerMock </groupId> The < artifactId > powermock - API - mockito2 < / artifactId > < version >2.0. 0</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId> <version>4.11</version> <scope>test</scope> </dependency>Copy the code
Relevant notes
// Tell JUnit to test using PowerMockRunner
@RunWith(PowerMockRunner.class)
// All classes that need to be tested are listed here. This applies to classes that simulate final classes or classes with final, private, static, or native methods
@PrepareForTest({RandomUtil.class})
// Ignore the classes in the package (do not load the specified package); Used to resolve a ClassLoader error after powerMock is used
@PowerMockIgnore("javax.management.*")
// Create an instance that calls the methods of real code
@InjectMocks
// A Mock instance is created with all properties and methods null (0 or NULL).
@Mock
Copy the code
The mock return value
// Mock expected value
1. PowerMockito.doReturn(expected).when(mockList).get(index);
2. PowerMockito.when(mockList.get(index)).thenReturn(expected);
// The mock exception returns
1. PowerMockito.doThrow(new IndexOutOfBoundsException()).when(mockList).get(index);
2. PowerMockito.when(mockList.get(index)).thenThrow(new IndexOutOfBoundsException());
// No return value
PowerMockito.doNothing().when(mockList).clear();
// Note: when().thenreturn () mode executes the original method, while doReturn().when() mode does not.
Copy the code
Check back
Mockito.verify(mockList).clear(); Mockito.verify(mockList, mockito.times (1)).clear(); // Validate the number of calls to the methodCopy the code
The mock parameters
AnyInt (), mockito.anystring, mockito.any (Class clazz), etc.
When we use a parameter matcher, we should use the matcher for all parameters. If you want to specify a specific value for a parameter, you need to use the mockito.eq () method.
The instance
Mock for different classes or methods.
------MockMapper.class
public interface MockMapper {public int count(MockModel model);
}
-----MockServiceImpl.class
@Service
public class MockServiceImpl {@Autowired
privateMockMapper mockMapper;public int count(MockModel model) {returnMockMapper. Count (model); }public boolean makeFile(String path) {
File file = new File(path);
return file.exists();
}
}
------MockUtil.class
public class MockUtil {
private static final Random random = new Random();
public static int nextInt(int bound) {
returnrandom.nextInt(bound); }}Copy the code
Mock normal methods
@RunWith(PowerMockRunner.class)
@PrepareForTest({MockUtil.class})
@PowerMockIgnore("javax.management.*")
public class MockExample {
// Inject a sample of the @mock annotation
@InjectMocks
private MockServiceImpl mockService;
@Mock
private MockMapper mockMapper;
/** * mock ordinary methods */
@Test
public void testSelectAppAdvertisementList(a) {
MockModel model = new MockModel();
PowerMockito.when(mockMapper.count(model)).thenReturn(2);
Assert.assertEquals(2, mockService.count(model)); }}Copy the code
Mock static methods
- Statement:
PowerMockito.mockStatic(Class clazz);
PrepareForTest({Class clazz});
Copy the code
- use
@RunWith(PowerMockRunner.class)
@PrepareForTest({MockUtil.class})
@PowerMockIgnore("javax.management.*")
public class MockStaticExample {@Test
public void testStaticMethod(a) {PowerMockito. MockStatic (MockUtil. Class); PowerMockito.when(MockUtil.nextInt(10)).thenReturn(7); Assert.assertEquals(7, MockUtil.nextInt(10)); }}Copy the code
A constructor within a Mock method
- The statement
- Pass the specified parameters to construct
PowerMockito.whenNew(*.class).withArguments(argument1, ...) .thenReturn(file)Copy the code
- Construct regardless of parameters
PowerMockito.whenNew(*.class).withAnyArguments().thenReturn(file)
Copy the code
- use
public final class FileUtils {
public static boolean isFile(String fileName) {
return new File(fileName).isFile();
}
}
----UT
@RunWith(PowerMockRunner.class)
@PrepareForTest({FileUtils.class})
public class MockStructureExample {
@Test
public void testIsFile(a) throws Exception {
String fileName = "test.txt";
File file = PowerMockito.mock(File.class);
PowerMockito.whenNew(File.class).withArguments(fileName).thenReturn(file);
PowerMockito.when(file.isFile()).thenReturn(true);
Assert.assertTrue("Return value false", FileUtils.isFile(fileName)); }}Copy the code
The mock class’s partial method spy
If we want to mock only part of an object and want the other methods to be the same, we can use the PowerMockito.spy method instead of the powerMockito.mock method. Thus, the method set by the WHEN statement calls the mock method; Methods that are not set by the WHEN statement call the original method.
- Statement:
PowerMockito.spy(Class clazz); / / class
T PowerMockito.spy(T object); / / spy object
Copy the code
- use
Example 1
public class StringUtils {
public static boolean isNotEmpty(final CharSequence cs) {
return! isEmpty(cs); }public static boolean isEmpty(final CharSequence cs) {
return cs == null || cs.length() == 0;
}
}
----UT
@RunWith(PowerMockRunner.class)
@PrepareForTest({ StringUtils.class })
public class StringUtilsTest {
@Test
public void testIsNotEmpty(a) {
String string = null;
boolean expected = true; PowerMockito.spy(StringUtils.class); PowerMockito.when(StringUtils.isEmpty(string)).thenReturn(! expected);boolean actual = StringUtils.isNotEmpty(string);
Assert.assertEquals("Return values are not equal", expected, actual); }}Copy the code
Example 2 Spy object
public class UserService {
private Long superUserId;
public boolean isNotSuperUser(Long userId) {
return! isSuperUser(userId); }public boolean isSuperUser(Long userId) {
return Objects.equals(userId, superUserId);
}
}
---- UT
@RunWith(PowerMockRunner.class)
public class UserServiceTest {
@Test
public void testIsNotSuperUser(a) {
Long userId = 1L;
boolean expected = false;
UserService userService = PowerMockito.spy(newUserService()); PowerMockito.when(userService.isSuperUser(userId)).thenReturn(! expected);boolean actual = userService.isNotSuperUser(userId);
Assert.assertEquals("Return values are not equal", expected, actual); }}Copy the code
The mock system class
Note: Since the URLEncoder class is a system class, we should prepare SystemClassUser for testing, since this is the URLEncoder class that calls the encode method. Example 1
public class SystemClassUser {
public String performEncode(a) throws UnsupportedEncodingException {
return URLEncoder.encode("string"."enc");
}
}
---UT
@RunWith(PowerMockRunner.class)
@PrepareForTest( { SystemClassUser.class })
public class SystemClassUserTest {
@Test
public void assertThatMockingOfNonFinalSystemClassesWorks(a) throws Exception {
mockStatic(URLEncoder.class);
expect(URLEncoder.encode("string"."enc")).andReturn("something");
replayAll();
assertEquals("something".newSystemClassUser().performEncode()); verifyAll(); }}Copy the code
Example 2
public class AppShell {
public Process exec(String command) {
return Runtime.getRuntime().exec(command);
}
}
----UT
@RunWith(PowerMockRunner.class)
@PrepareForTest(AppShell.class)
public class AppShellTest {
@Mock private Runtime mockRuntime;
@Test
public void test(a) {
PowerMockito.mockStatic(Runtime.class);
when(Runtime.getRuntime()).thenReturn(mockRuntime);
when(mockRuntime.exec()).thenReturn("whatever you want");
// do the rest of your test}}Copy the code
Mock class private methods, properties
- Statement:
- Mock private properties
// The first way; Native JUnit is used for unit testing
ReflectionTestUtils.setField(obj, fieldName, value);
// The second way; Whitebox. SetInternalState powermock
Whitebox.setInternalState(obj, fieldName, value);
Copy the code
- Mock private methods
1. PowerMockito.stub(PowerMockito.method(UserService.class, "isSuperUser", Long.class)).toReturn(! expected);2. PowerMockito.when(userService, "isSuperUser", userId).thenReturn(! expected);Copy the code
- use
@Service
public class UserService {
@Value("${system.userLimit}")
private Long userLimit;
public Long getUserLimit(a) {
return userLimit;
}
private boolean isSuperUser(Long userId) {
return Objects.equals(userId, superUserId);
}
}
-----UT
public class UserServiceTest {
@Autowired
private UserService userService;
// Mock private attributes
@Test
public void testGetUserLimit(a) {
Long expected = 1000L;
ReflectionTestUtils.setField(userService, "userLimit", expected);
// or the following kind
// Whitebox.setInternalState(userService, "userLimit", expected);
Long actual = userService.getUserLimit();
Assert.assertEquals("Return values are not equal", expected, actual);
}
// Mock private methods
@Test
public void testIsNotSuperUser(a) throws Exception {
Long userId = 1L;
boolean expected = false;
UserService userService = PowerMockito.spy(new UserService());
PowerMockito.when(userService, "isSuperUser", userId).thenReturn(! expected); PowerMockito.stub(PowerMockito.method(UserService.class,"isSuperUser", Long.class)).toReturn(! expected);boolean actual = userService.isNotSuperUser(userId);
Assert.assertEquals("Return values are not equal", expected, actual); }}Copy the code
Refer to the link
Github.com/powermock/p…