EasyMock 单元测试过程中模拟相关类的实例

在单元测试的过程中,我们希望仅仅测试一个类的功能是否正常,但是一个类中往往会引用其他类,而不得在测试一个类的同时其它类相关也进行了测试。 看上去结果很好,一个测试不仅测试了目标类又测试了其它类,但是这样的交叉测试导致一个致命问题,单元测试不再测试单一的类,一旦一个类出现问题会影响到多个单元测试,同样一个测试失败也不知道到底是哪个类出现问题。单元测试变成了集成测试,失去了单元测试的意义。 

因此,合理的单元测试应该是一个类写一个测试,涉及到的其他引用类怎么办? EasyMock正是为此而生,它可以模拟出一个相关类的的行为。具体来讲,一个类主要就是所拥有的方法的行为,而EasyMock可以预先设定一个方法传入什么样的参数返回什么样的值,并且可以设定在程序中调用多少次,等等。这样一来单元测试就是真正意义的“单元”测试,使得测试代码更加精准。

下面是一个简单的例子:

被测试类:

public class BaseAvailabilityService implements AvailabilityService {
	
	
	private IConvert convert;
	private IService service;
	private IProfileService profile;
	
	@Override
	public Availability getAvailability(AvailabilityCriteria criteria, Contract contract) {
		final HotelSearchCriteria hsc = (HotelSearchCriteria) criteria.getCriteria();
		final ChannelHotelMapping hotelMapping = profile.getChannelHotelMapping(contract.getChannelCode(), hsc.getUniqueHotelCode());
		
		GetAvailRS avail = service.getAvailability(hotelMapping.getChannel().getAccount(), convert.toGetAvailRQ(criteria, hotelMapping));
		return convert.toAvailability(avail, criteria.getGuestCount().getAdultCount(), hotelMapping, null);
	}
	@Required
	public void setConvert(IStarwoodConvert convert) {
		this.convert = convert;
	}

	@Required
	public void setService(IStarwoodService service) {
		this.service = service;
	}
	@Required
	public void setProfile(IProfileService profile) {
		this.profile = profile;
	}

}
测试代码:

public class AvailabilityServiceTest {
	
	private BaseAvailabilityService availService = new BaseAvailabilityService();
	private IConvert convert;
	private IService service;
	private IProfileService profile;
	@Before
	public void startup(){
		convert = EasyMock.createMock(IConvert.class);
		service = EasyMock.createMock(IService.class);
		profile = EasyMock.createMock(IProfileService.class);
		availService.setConvert(convert);
		availService.setProfile(profile);
		availService.setService(service);
	}
	@Test
	public void testGetAvailability(){
		ChannelHotelMapping mapping = new ChannelHotelMapping();
		mapping.setChannel(new Channel());
		
		AvailabilityCriteria availCriteria = new AvailabilityCriteria();
		availCriteria.setCriteria(new HotelSearchCriteria());
		availCriteria.setGuestCount(new GuestCount());
		
		GetAvailRQ getAvailRQ = new GetAvailRQ();
		
		EasyMock.expect(profile.getChannelHotelMapping(null, null)).andReturn(mapping);
		EasyMock.expect(service.getAvailability(new Account(null,null), getAvailRQ)).andReturn(new GetAvailRS());
		EasyMock.expect(convert.toAvailability(new GetAvailRS(), null,mapping, null)).andReturn(new Availability());
		EasyMock.expect(convert.toGetAvailRQ(availCriteria, mapping)).andReturn(getAvailRQ);
		EasyMock.replay(profile,service,convert);
		availService.getAvailability(availCriteria, new Contract());
		EasyMock.verify(profile,service,convert);
	}
}

以上的例子中,Mock的方法都有参数与返回值,如果是有参数没有返回值的方法, 完全不能这样模拟了,可以用一下方式, 即在模拟调用的下一行,执行expectLastCall():

mokedObject.someFunction(sameObject);
EasyMock.expectLastCall();

还有一个问题,如果是想设定一个方法无论传入任何值,都返回特定值,如何设定? 可以使用参数可以使用EasyMock.isA(SomeObject.class),只要是SomeObject的实例都将执行预设的行为,如:

mokedObject.someFunction(EasyMock.isA(Object.class));

阅读更多
文章标签: EasyMock
个人分类: 框架
想对作者说点什么? 我来说一句

EasyMock单元测试例子

2013年12月31日 27KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭