天天看点

powerMock spring junit test

在与外部接口联调时,受制于接口的环境,采用mock接口的方式进行逻辑的单元测试,我感觉挺方便的。而且使用简单,一看代码你就明白了。

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.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.slf4j.Logger;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.vista.mall.fact.product.ProductionStatus;

import javax.annotation.Resource;
import java.net.MalformedURLException;

import static org.mockito.Mockito.when;

/**
 * Created by le on 2016/11/30.
 */
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@PowerMockIgnore({"javax.net.ssl.*","javax.management.*"})
@ContextConfiguration(locations = {"classpath:spring/applicationContext-*.xml"})
public class ErpProductSyncServiceTest {
    private static final Logger logger = org.slf4j.LoggerFactory.getLogger(ErpProductSyncServiceTest.class);

    @Mock
    private HessianServiceFactory hessianServiceFactory;

    @Resource
    @InjectMocks
    private ErpProductSyncService erpProductSyncService;


    @Before
    public void before() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void putOffShelvesTest() {
        String productId = "1003321";
        String channelId = "30104";
        ProductionStatus productionStatus = new ProductionStatus();
        productionStatus.setStatus("0");
        productionStatus.setChangeTime("2016-10-09 00:00:23");
        productionStatus.setProductId(productId);
        try {
            when(hessianServiceFactory.judgeProductionStatus(productId, channelId)).thenReturn(productionStatus);
            erpProductSyncService.setHessianServiceFactory(this.hessianServiceFactory);
            logger.info("{}",erpProductSyncService.judgeProductionStatus(productId, channelId));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
}
           

有几点注意的:

  • 如果是 @Mock, 那就是通常的方式,service里面的provider完全被Mock实例替换,所有的调用都是针对Mock生成类的。
  • 运行测试用例的时候,可能会报错,需要忽略掉一些类的mock,例如:@PowerMockIgnore({“javax.net.ssl.“,”javax.management.“})
  • 如果是 @Autowired 加 @Spy , 那么对于定制了返回值的会调用 Mock实例,否则会调用真实注入的属性,但是这里有一个限制,如果是代理类会报错,比如Spring 的AOP代理。
  • 对于AOP的代理类,如果想一部分用Mock,一部分用真实的实例,感觉目前是有些困难,暂时想到的办法就是写两个测试类,一个注入真实属性,一个注入mock属性。
  • 方法调用时,如果不想指定一个明确的参数,就可以用下面这样的写法来表示任意的参数。

powermock 可以mock掉dao、service、静态方法、私有方法等等,对于模拟那些未实现或者环境问题的接口或实现类很方便,写测试用例时看起来优雅一点。

参考文章:

http://www.2cto.com/kf/201303/196397.html

http://www.cnblogs.com/zemliu/p/3369476.html

继续阅读