Mockito+JUnit单元测试时引用传递的offers对象未更新问题
问题原因
- 你用
@Mock注解声明的OfferService对象默认所有方法都是桩实现,不会执行真实方法逻辑。即便添加doCallRealMethod配置,mock出来的OfferService实例内部的MyDAO依赖并没有被注入,执行真实方法也无法完成数据库查询和offers对象更新。 - 测试类的
setUp方法中ItemService是局部变量,testBuildItems方法无法访问该实例,会编译报错。 - 原业务代码
ItemService的构造函数仅接收OfferService一个入参,测试代码中传两个参数的写法不符合原有定义。
解决方案
方案1(推荐,符合单元测试隔离原则)
直接mock OfferService.fetchInfoFromDB方法的行为,手动更新传入的offers对象,不需要执行OfferService的真实逻辑:
@RunWith(PowerMockRunner.class) @PrepareForTest(ItemService.class) public class ItemServiceTest{ @Mock private OfferService offerService; // 提升为成员变量,测试方法可访问 private ItemService itemService; @Before public void setUp() throws Exception { // 匹配原有构造函数定义 itemService = new ItemService(offerService); } @Test public void testBuildItems(){ ItemInfo itemInfo = buildItemInfo(); OfferDetail offerDetail = buildOfferDetail(); // 用Answer拦截方法调用,手动更新传入的offers对象 doAnswer(invocation -> { Offers<Offer> offers = invocation.getArgument(0); // 按照业务逻辑填充offers的内容,模拟真实方法的更新效果 Offer mockOffer = new Offer(); mockOffer.setDetail(offerDetail); offers.add(mockOffer); return null; // 原方法为void返回 }).when(offerService).fetchInfoFromDB(any(Offers.class)); List<Item> items = itemService.buildItems(itemInfo); Assert.assertNotNull(items); // 可补充断言验证items的属性是否符合预期 } }
方案2(需要执行OfferService真实逻辑时使用)
用@Spy代替@Mock声明OfferService,同时为其注入mock的MyDAO依赖:
@RunWith(PowerMockRunner.class) @PrepareForTest(ItemService.class) public class ItemServiceTest{ @Mock private MyDAO myDao; // Spy默认执行真实方法,初始化时传入mock的myDao @Spy private OfferService offerService = new OfferService(myDao); private ItemService itemService; @Before public void setUp() throws Exception { itemService = new ItemService(offerService); // 如果OfferService没有接收MyDAO的构造函数,用反射赋值 Field daoField = OfferService.class.getDeclaredField("myDao"); daoField.setAccessible(true); daoField.set(offerService, myDao); } @Test public void testBuildItems(){ ItemInfo itemInfo = buildItemInfo(); OfferDetail offerDetail = buildOfferDetail(); when(myDao.getDetailsById(Mockito.anyLong())).thenReturn(offerDetail); List<Item> items = itemService.buildItems(itemInfo); Assert.assertNotNull(items); } }
内容的提问来源于stack exchange,提问作者Som
相关产品推荐
相关产品推荐

