1.Powermockito和Mockito之间的关系可以参考我的另一篇博客
Powermockito和Mockito测试框架分析以及一个简单的脚手架+单测的注意事项
2.maven依赖配置
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.powermock/powermock-api-mockito2 -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.19.0</version>
<scope>test</scope>
</dependency>
</dependencies>
3.java 代码准备
@Repository
public interface UserDAO {
UserDTO getById(Long userId);
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDTO {
private Long userId;
private String username;
}
@Service
public class UserService {
@Resource
private UserDAO userDAO;
public UserDTO getById(Long userId) {
if (Objects.isNull(userId) || userId == 0l) {
return new UserDTO(1l, "zxliuyu");
}
return userDAO.getById(userId);
}
public UserDTO getByIdAllowException(Long userId) {
if (Objects.isNull(userId) || userId == 0l) {
throw new RuntimeException("用户Id不能为空");
}
return userDAO.getById(userId);
}
public UserDTO getByIdUseStaticMethod(Long userId) {
userId = HttpClient.getUserId();
return userDAO.getById(userId);
}
public UserDTO getByIdContainInternalCall(Long userId) {
userId = getUserId();
return userDAO.getById(userId);
}
public Long getUserId() {
return 1l;
}
}
4.单元测试代码
@RunWith(PowerMockRunner.class)
@PrepareForTest(HttpClient.class)
public class UserServiceTest {
@InjectMocks
private UserService userService;
@Mock
private UserDAO userDAO;
@Rule
public ExpectedException exception = ExpectedException.none();
@Before
public void init() {
MockitoAnnotations.initMocks(this);
PowerMockito.mockStatic(HttpClient.class);
}
@Test
public void testGetByIdUserIdIsNull() {
Long userId = null;
long expectedUserId = 1l;
UserDTO user = userService.getById(userId);
Mockito.verify(userDAO, Mockito.times(0)).getById(any());
Assertions.assertThat(user.getUserId()).isEqualTo(expectedUserId);
}
@Test
public void testGetById() {
Long userId = 1l;
long expectedUserId = 1l;
when(userDAO.getById(any())).thenReturn(new UserDTO(1l, "zxliuyu"));
UserDTO user = userService.getById(userId);
Mockito.verify(userDAO, Mockito.times(1)).getById(any());
Assertions.assertThat(user.getUserId()).isEqualTo(expectedUserId);
}
@Test
public void testGetByIdAllowExceptionUserIdIsNull() {
Long userId = null;
exception.expect(RuntimeException.class);
exception.expectMessage("用户Id不能为空");
userService.getByIdAllowException(userId);
}
@Test
public void testGetByIdAllowException() {
Long userId = 1l;
long expectedUserId = 1l;
when(userDAO.getById(any())).thenReturn(new UserDTO(1l, "zxliuyu"));
UserDTO user = userService.getByIdAllowException(userId);
Mockito.verify(userDAO, Mockito.times(1)).getById(any());
Assertions.assertThat(user.getUserId()).isEqualTo(expectedUserId);
}
@Test
public void testGetByIdUseStaticMethod() {
Long userId = 1l;
long expectedUserId = 1l;
when(userDAO.getById(any())).thenReturn(new UserDTO(1l, "zxliuyu"));
when(HttpClient.getUserId()).thenReturn(userId);
UserDTO user = userService.getByIdUseStaticMethod(userId);
Mockito.verify(userDAO, Mockito.times(1)).getById(any());
Assertions.assertThat(user.getUserId()).isEqualTo(expectedUserId);
}
@Test
public void testGetByIdContainInternalCall() {
Long userId = 1l;
long expectedUserId = 1l;
UserService userServiceSpy = PowerMockito.spy(userService);
when(userDAO.getById(any())).thenReturn(new UserDTO(1l, "zxliuyu"));
doReturn(userId).when(userServiceSpy).getUserId();
UserDTO user = userServiceSpy.getByIdContainInternalCall(userId);
Mockito.verify(userDAO, Mockito.times(1)).getById(any());
Assertions.assertThat(user.getUserId()).isEqualTo(expectedUserId);
}
}
执行结果
5.注意事项
1.如果出现方法内部调用,需要使用spy进行打桩,然后该类所有的方法都用打桩后的对象调用
doReturn(userId).when(userServiceSpy).getUserId();
2.尽量不要mock使用私有方法,会有一些问题,如果私有方法需要单元测试,建议改成公共方法,加上VisibleForTesting代表这个方法是为了测试才改成公共方法
@VisibleForTesting
public Long getUserId() {
return 1l;
}
|