在与外部接口联调时,受制于接口的环境,采用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属性。
- 方法调用时,如果不想指定一个明确的参数,就可以用下面这样的写法来表示任意的参数。
Mockito.when(this.provider.getRevenueRoute(Matchers.anyString(), Matchers.anyString(), Matchers.anyBoolean())).thenReturn(rm);
powermock 可以mock掉dao、service、静态方法、私有方法等等,对于模拟那些未实现或者环境问题的接口或实现类很方便,写测试用例时看起来优雅一点。
参考文章:
http://www.2cto.com/kf/201303/196397.html
http://www.cnblogs.com/zemliu/p/3369476.html