当前位置:网站首页>Powermock actual combat
Powermock actual combat
2022-07-21 19:03:00 【Ibrahimo】
Version depends on
Be careful :powermockito And mockito Versions are prone to inconsistency .
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<!-- 7.5.0 Are not compatible -->
<version>7.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<!-- <artifactId>mockito-inline</artifactId> -->
<artifactId>mockito-core</artifactId>
<version>3.12.4</version>
<scope>test</scope>
</dependency>
<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-testng</artifactId>
<version>2.0.9</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
</exclusion>
</exclusions>
</dependency>
Business background
User login module , The code is layered as follows . Support multiple login modes .
- controller
- service
- abstract Abstract implementation
- MobileService,EmailService,AccountService Deal with... Separately Three Different login methods
- mapper
- po
- other
- Utils : Static methods Tool class
- PasswordEncoder : Ordinary encryption method class
The code structure
Business code
Utils
public interface Utils {
static boolean checkIsEmail(String email) {
if ((email != null) && (!email.isEmpty())) {
return Pattern.matches("^(\\w+([-.][A-Za-z0-9]+)*){3,18}@\\w+([-.][A-Za-z0-9]+)*\\.\\w+([-.][A-Za-z0-9]+)*$", email);
}
return false;
}
static void checkIsMobile(String mobile) {
if ((mobile != null) && (!mobile.isEmpty())) {
boolean match = Pattern.matches("^((13[0-9])|(14[0|5|6|7|9])|(15[0-3])|(15[5-9])|(16[6|7])|(17[2|3|5|6|7|8])|(18[0-9])|(19[1|8|9]))\\d{8}$", mobile);
if(match){
return;
}
}
throw new RuntimeException("is not mobile");
}
}
PasswordEncoder
public class PasswordEncoder {
private static final Logger logger = LoggerFactory.getLogger(PasswordEncoder.class);
public String encryptPassword(String plainText) {
String encryptedText = plainText;
logger.debug("{} encrypted result: {}", plainText, encryptedText);
//todo encode Plaintext
return encryptedText;
}
}
UserMapper
public interface UserMapper {
User get(String account);
User getByMobile(String mobile);
User getByEmail(String email);
}
XService
Interface
public interface ILoginService {
boolean support(String input);
Long login(String input, String password);
}
controller: Modify member properties 、 Parent property mock
Business code
public class UserController {
//mocklist
private List<ILoginService> loginServiceList;
public UserController(List<ILoginService> loginServiceList ){
this.loginServiceList = loginServiceList;
}
public Long login(String input , String password){
ILoginService loginService = loginServiceList.stream().filter(service -> service.support(input)).findFirst().orElseThrow(() -> new RuntimeException(" Unrecognized account type "));
return loginService.login(input, password);
}
}
test
public class UserControllerTest {
@InjectMocks
@Spy
private UserController userController;
@Mock
private List<ILoginService> loginServiceList;
@BeforeClass
public void setUp() throws IllegalAccessException {
MockitoAnnotations.openMocks(this);
}
String input = "[email protected]";
String password = "123456";
@Test
public void testLogin_throw() {
try {
userController.login(input, password);
Assert.fail("expect RuntimeException");
} catch (Exception e) {
Assert.assertTrue(e instanceof RuntimeException);
}
}
@Test
public void testLogin_pass() throws IllegalAccessException {
ILoginService loginService = mock(ILoginService.class);
when(loginService.support(anyString())).thenReturn(true);
when(loginService.login(anyString(), anyString())).thenReturn(99L);
List<ILoginService> list2 = Lists.newArrayList(loginService);
// To reset mock Object member variable attribute
MemberModifier.field(UserController.class, "loginServiceList").set(userController, list2);
Long userId = userController.login(input, password);
Assert.assertTrue(userId.equals(99L));
}
}
AbstractService: abstract class mock
Business code
public abstract class AbstractLoginService implements ILoginService {
private static final Logger logger = LoggerFactory.getLogger(AbstractLoginService.class);
@Resource
private PasswordEncoder passwordEncoder;
protected final ThreadLocal<User> threadLocal = new ThreadLocal<>();
@Override
public Long login(String input, String password) {
logger.info("start to login {}/{}",input,password);
getUserInternal(input);
try{
User user = threadLocal.get();
String encodedPassword = passwordEncoder.encryptPassword(password);
if (user.getPassword().equals(encodedPassword)) {
return user.getId();
}
throw new RuntimeException(" Wrong username and password ");
}finally {
threadLocal.remove();
}
}
public abstract void getUserInternal(String input);
}
test
public class AbstractLoginServiceTest {
@InjectMocks
// @Spy -- Can't use spy , Pile driving abstract class
private AbstractLoginService abstractLoginService;
@Mock
private PasswordEncoder passwordEncoder;
@Mock
protected ThreadLocal<User> threadLocal;
@BeforeClass
public void setUp(){
//mock abstract class
abstractLoginService = Mockito.mock(AbstractLoginService.class, Mockito.CALLS_REAL_METHODS);
MockitoAnnotations.openMocks(this);
}
@Test
public void testLogin() throws IllegalAccessException {
// mock(AbstractLoginService.class), Therefore, real member variables cannot be used threadLocal, I can't inject,
// It must be manual here inject
MemberModifier.field(AbstractLoginService.class, "threadLocal").set(abstractLoginService, threadLocal);
//mock void Method ,do-nothing
// doNothing().when(threadLocal).remove();
User user = mock(User.class);
when(threadLocal.get()).thenReturn(user);
when(user.getPassword()).thenReturn("abc");
when(passwordEncoder.encryptPassword(anyString())).thenReturn("abc");
abstractLoginService.login("123", "xxx");
Assert.assertTrue(true);
try{
when(passwordEncoder.encryptPassword(anyString())).thenCallRealMethod();
abstractLoginService.login("123", "xxx");
Assert.fail("expect Wrong username and password ");
}catch (Exception e){
Assert.assertTrue(e instanceof RuntimeException);
Assert.assertTrue(e.getMessage().equals(" Wrong username and password "));
}
}
}
MailLoginService: Static methods + Ordinary void() Method mock
Business class
public class MailLoginService extends AbstractLoginService {
private static final Logger logger = LoggerFactory.getLogger(MailLoginService.class);
@Resource
private UserMapper userMapper;
@Override
public boolean support(String email) {
return Utils.checkIsEmail(email);
}
@Override
public void getUserInternal(String email) {
User user = userMapper.getByEmail(email);
threadLocal.set(user);
}
}
The test method
//@MockPolicy(Slf4jMockPolicy.class)
@PowerMockIgnore({
"javax.management.*", "jdk.internal.reflect.*"})
@PrepareForTest(Utils.class)
public class MailLoginServiceTest extends PowerMockTestCase {
@InjectMocks
@Spy
private MailLoginService mailLoginService;
@Mock
private UserMapper userMapper;
@BeforeClass
public void setUp(){
MockitoAnnotations.openMocks(this);
//static mock
PowerMockito.mockStatic(Utils.class);
}
@Test
public void testSupport() {
//static
PowerMockito.when(Utils.checkIsEmail(anyString())).thenReturn(true);
Assert.assertTrue(mailLoginService.support("email"));
PowerMockito.when(Utils.checkIsEmail(anyString())).thenReturn(false);
Assert.assertFalse(mailLoginService.support("email"));
}
@Test
public void testGetUserInternal() throws IllegalAccessException {
User user = mock(User.class);
when(userMapper.getByEmail(anyString())).thenReturn(user);
mailLoginService.getUserInternal("abc");
// Modify the parent property -- by null
MemberModifier.field(MailLoginService.class, "threadLocal").set(mailLoginService, null);
try{
mailLoginService.getUserInternal("abc");
Assert.fail("expect NPE fail");
}catch (Exception e) {
Assert.assertTrue( e instanceof NullPointerException);
}
}
}
MobileLoginService: static void Method mock
Business methods
public class MobileLoginService extends AbstractLoginService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource
private UserMapper userMapper;
@Override
public boolean support(String mobile) {
try{
Utils.checkIsMobile(mobile);
return true;
}catch (Exception e) {
return false;
}
}
@Override
public void getUserInternal(String mobile) {
User user = userMapper.getByMobile(mobile);
threadLocal.set(user);
}
}
The test method
@PowerMockIgnore({
"javax.management.*", "jdk.internal.reflect.*"})
@PrepareForTest(Utils.class)
public class MobileLoginServiceTest extends PowerMockTestCase {
@InjectMocks
@Spy
private MobileLoginService mobileLoginService;
@Mock
private UserMapper userMapper;
@BeforeClass
public void setUp(){
MockitoAnnotations.openMocks(this);
PowerMockito.mockStatic(Utils.class);
}
@Test
public void testSupport() throws Exception {
// mock static The return value of the method is void
PowerMockito.doNothing().when(Utils.class,"checkIsMobile",any(String.class));
Utils.checkIsMobile("abc");
Assert.assertTrue(true);
PowerMockito.doThrow(new UnsupportedOperationException(" Unsupported operations ")).when(Utils.class,"checkIsMobile",any(String.class));
try{
Utils.checkIsMobile("abc");
Assert.fail("expect Unsupported operations ");
}catch (Exception e){
Assert.assertTrue(e instanceof UnsupportedOperationException);
}
}
}
边栏推荐
- liunx 批量杀死同名进程
- 第一部分—C语言基础篇_9. 复合类型(自定义类型)
- 软件测试面试题:Internet采用哪种网络协议?该协议的主要层次结构?Internet物理地址和IP地址转换采用什么协议?
- C language -- the use and Simulation of library function qsort
- kubernetes的这几种存储卷,别再傻傻分不清了
- 点亮第一个LED
- Pure dry content: I'm still hesitant about the comparison between IVX and mendix. Let's see the little partner who chose the low code platform
- ESP 特权隔离机制介绍
- 论文翻译解读:Anytime Bottom-Up Rule Learning for Knowledge Graph Completion【AnyBURL】
- Test the mock data method of knowing and knowing
猜你喜欢
Part I - Fundamentals of C language_ 8. Memory management
V853开发板硬件资料——RISC-V核E907用户手册
高质量WordPress下载站模板5play主题源码
Practice of online problem feedback module (IX): realize image upload function (Part 2)
用VIM正则表达式进行批量替换的小练习
全新红包封面平台可搭建分站独立后台的源码
Apple released watchos 8.7 with bug fixes and security updates
If the recommendation effect is not satisfactory, it's better to try to learn the propeller chart
ESP 特权隔离机制介绍
nexus 5X刷机并使用Magisk获取root权限
随机推荐
C语言常量与变量
Banks are not Tangseng meat banks are solid barriers to financial security.
电子招标采购商城系统:优化传统采购业务,提速企业数字化升级
Postgresql源码(64)查询执行——子模块Executor(2)执行前的数据结构和执行过程
Tutorial (7.0) 03 Forticlient EMS configuration and Management * forticlient EMS * Fortinet network security expert NSE 5
Resttemplate calls post\get
Design of the multi live architecture in different places of the king glory mall
TCP協議
[QNX Hypervisor 2.2用户手册]8.5 vCPU和Hypervisor性能
Brush notes - find
第一部分—C语言基础篇_10. 文件操作
ESP 特权隔离机制介绍
ACM training July 5
Small exercise of batch replacement with VIM regular expression
MySQL -bash: mysqldump: command not found error resolution
The new red envelope cover platform can build the source code of the independent background of the sub station
Test the mock data method of knowing and knowing
canal. Deployer-1.1.6 encountered dump address has an error, retrying Caused by problem
面试 02
【obs】基于cmake的Release带符号构建