现在我有一些单元测试的问题?
订单时应显示一些可用的优惠券列表
public List<Coupon> getAvailableCouponsWhenOrder(String productCategory, int productPrice, String shopId, String userId){
// get all available coupons -- that is not used
List<Coupon> couponList = couponMapper.queryCoupons(userId);
// filter coupons
List<Coupon> availableList = new ArrayList<>();
for (Coupon coupon : couponList) {
// some coupon only support specific category, e.g. book, phone
if(!checkCategory(coupon,productCategory)){
continue;
}
// some coupon have use condition , e.g. full 100 then minus 50
if(!checkPrice(coupon,productPrice)){
continue;
}
// you cannot use other shop's coupon
if(!checkShopCoupon(coupon,shopId)){
continue;
}
availableList.add(coupon);
}
return availableList;
}
并且低于单元测试
@Test
public void test_exclude_coupon_which_belong_to_other_shop(){
String productCategory = "book";
int productPrice = 200;
String shopId = RandomStringUtils.randomAlphanumeric(10);
String userId = RandomStringUtils.randomAlphanumeric(10);
Coupon coupon = new Coupon();
String anotherShopId = RandomStringUtils.randomAlphanumeric(10);
coupon.setShopId(anotherShopId); // other shop's coupon
coupon.setCategory("book"); // only use for buying book
coupon.setFullPrice(200); // full 200 minus 50
coupon.setPrice(50);
when(couponMapper.queryCoupons(userId)).thenReturn(newArrayList(coupon));
List<Coupon> availableCoupons = service.getAvailableCoupons(productCategory, productPrice, shopId, userId);
// check whether exclude other shop's coupon
assertEquals(0, availableCoupons.size());
}
但即使它过去了,我仍然不相信它是对的?因为可能先前的检查失败,例如checkCategory总是返回false?
那么如何知道它真的执行checkShopCoupon
?
答案 0 :(得分:0)
请远离使用模拟框架来测试您的私有方法。 (可能!)唯一需要模拟的是这个行:
List<Coupon> couponList = couponMapper.queryCoupons(userId);
这很简单:您必须确保列表couponList
具有特定内容。换句话说:您创建了一整套不同的测试方法,每个测试方法都使用不同的值预先设置couponList
。然后你检查返回的列表是否符合你的期望。
并且为了记录:更好地使用一个而且只断言一个人确实需要:
assertThat(service.getAvailableCoupons(productCategory, productPrice, shopId, userId), is(somePredefinedList));
(其中是是Hamcrest匹配器方法)
长话短说:您可能需要使用模拟来控制对queryCoupons()的调用的返回值 - 但这是唯一需要在此处进行模拟的部分!
答案 1 :(得分:0)
在测试中需要检查两件事:逻辑正确并且逻辑被正确调用。在你的情况下,它可以是:
CouponMapperTest#queryingCouponReturnsCouponByUserId()
getAvailableCouponsWhenOrder()
的组件测试(没有模拟),然后调用couponMapper.queryCoupons(userId)
但是根据建议的方法,您可能会遇到大量的组件测试,这可能需要一段时间才能运行。为此,您需要构建一个平衡的测试金字塔(here is a thorough example),以确保您有大量的单元测试,更少的组件测试和更少的系统测试。有人建议:
模拟框架为维护测试增加了很多负担。如果某些东西被重构,你经常需要改变一大堆测试。模拟框架的另一个问题 - 您必须单独测试事物,同时还必须确保项目作为一个整体工作。
所以我不鼓励使用模拟,除非它是你的应用程序的边界或者它是一个非常重的依赖。