PowerMock使用详解

1. PowerMock是什么?

PowerMock是一个Java模拟框架,用于解决测试问题。

举个例子,你在使用Junit进行单元测试时,并不想让测试数据进入数据库,怎么办?这个时候就可以使用PowerMock,拦截数据库操作,并模拟返回参数。

2. PowerMock包引入

<!-- PowerMock JUnit 4.4+ Module -->
<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-module-junit4</artifactId>
  <version>2.0.0</version>
  <scope>test</scope>
</dependency>
<!-- PowerMock Mockito2 API -->
<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-api-mockito2</artifactId>
  <version>2.0.0</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.11</version>
  <scope>test</scope>
</dependency>

3. 重要注解说明

@RunWith(PowerMockRunner.class) // 告诉JUnit使用PowerMockRunner进行测试
@PrepareForTest({RandomUtil.class}) // 所有需要测试的类列在此处,适用于模拟final类或有final, private, static, native方法的类
@PowerMockIgnore("javax.management.*") //为了解决使用powermock后,提示classloader错误

4. 示例

4.1 普通Mock

/***********************Prepare****************************/

public interface MockMapper {
  public int count(MockModel model);

}

@Service
public class MockServiceImpl {
  @Autowired
  private MockMapper mockMapper;

  public int count(MockModel model) {
    return mockMapper.count(model);
  }
}

/*****************************************************/

@RunWith(PowerMockRunner.class) // 告诉JUnit使用PowerMockRunner进行测试
@PrepareForTest({MockUtil.class}) // 所有需要测试的类列在此处,适用于模拟final类或有final, private, static, native方法的类
@PowerMockIgnore("javax.management.*") //为了解决使用powermock后,提示classloader错误
public class MockExample {
    // 将@Mock注解的示例注入进来
    @InjectMocks
    private MockServiceImpl mockService;
    @Mock
    private MockMapper mockMapper;
    
    /**
     * mock普通方法
     */
    @Test
    public void testSelectAppAdvertisementList() {
        MockModel model = new MockModel();
        PowerMockito.when(mockMapper.count(model)).thenReturn(2);
        
        Assert.assertEquals(2, mockService.count(model));
    }
}

2. Mock静态方法

/************************Prepare****************************/
public class MockUtil {
    private static final Random random = new Random();
    
    public static int nextInt(int bound) {
        return random.nextInt(bound);
    }
}
/***************************************************/

@RunWith(PowerMockRunner.class) // 告诉JUnit使用PowerMockRunner进行测试
@PrepareForTest({MockUtil.class}) // 所有需要测试的类列在此处,适用于模拟final类或有final, private, static, native方法的类
@PowerMockIgnore("javax.management.*") //为了解决使用powermock后,提示classloader错误
public class MockExample {
  @Test 
  public void testStaticMethod() { 
    PowerMockito.mockStatic(MockUtil.class); 
    PowerMockito.when(MockUtil.nextInt(10)).thenReturn(7); 
    Assert.assertEquals(7, MockUtil.nextInt(10)); 
  }
}

3. Mock方法内new出来的对象

/****************************************************/
public boolean makeFile(String path) {
    File file = new File(path);
    return file.exists();
}
/****************************************************/

@RunWith(PowerMockRunner.class) // 告诉JUnit使用PowerMockRunner进行测试
@PrepareForTest({MockUtil.class, MockServiceImpl.class}) // 所有需要测试的类列在此处,适用于模拟final类或有final, private, static, native方法的类
@PowerMockIgnore("javax.management.*") //为了解决使用powermock后,提示classloader错误
public class MockExample {
    // 将@Mock注解的示例注入进来
    @InjectMocks
    private MockServiceImpl mockService;
        @Test
    public void testNewObject() throws Exception {
        File file = PowerMockito.mock(File.class);
        PowerMockito.whenNew(File.class).withArguments("abc").thenReturn(file);
        PowerMockito.when(file.exists()).thenReturn(true);
        Assert.assertTrue(mockService.makeFile("abc"));    
    }
}

4.不让测试数据进入数据库(关键点:)

不让测试数据进入数据库的关键点:@Transactional、@Rollback(true)

Test用例:

import com.alibaba.fastjson.JSON;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.internal.util.MockUtil;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Random;


/**
 * PowerMock是一个Java模拟框架,用于解决测试问题。
 * 举个例子,你在使用Junit进行单元测试时,并不想让测试数据进入数据库,怎么办?这个时候就可以使用PowerMock,拦截数据库操作,并模拟返回参数。
 */
@RunWith(SpringJUnit4ClassRunner.class)
@PrepareForTest({MockUtil.class})
@PowerMockIgnore("javax.management.*")
@Transactional
@ContextConfiguration(locations = {"classpath*:applicationContext.xml"})
public class DemoMockTest {

    //将@Mock注解的示例注入进来
    @Resource
    @InjectMocks
    private DemoService demoService;

    @Mock
    private SingleService singleService;

    public int randomNum(int min, int max) {
        Random random = new Random();
        int s = random.nextInt(max) % (max - min + 1) + min;
        return s;
    }
    /**
     * singleSequenceService服务mock,mock结果为ID值
     */
    @Before
    public void testInsertMockSuccess() {
        Random random = new Random();
        long id = random.nextInt(999999) % (1000000);
        MockitoAnnotations.initMocks(this);
        PowerMockito.when(singleService.getId("demo")).thenReturn(id);
    }

    @Rollback(true)
    @Test
    public void insert() {
        Demo demo = new Demo();
        demo.setSellerName("AA技术有限公司");
        demo.setSellerNo("10000");

        demoService.insert(demo);
    }

    @Test
    public void getDemo() {
        Demo demo = demoService.getDemo(1L);
        System.out.println(JSON.toJSONString(demo));
    }

}

demoService实现:

/**
 * Demo
 */
@Service("demoService")
public class DemoServiceImpl implements DemoService {

	@Resource
	private DemoManager demoManager;

	@Resource
	private SingleService singleService;

	@Override
	public void insert(Demo demo) {
		//唯一ID生成(分库分表)
		long id = singleService.getId("demo");
		demo.setId(id);
		demoManager.insert(demo);
	}

}

文章来源:https://www.cnblogs.com/lovezmc/p/11232112.html

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值