我有一个具有多个字段依赖项的Spring服务,如下所示。其中一个依赖关系(thirdPartyService
(与外部应用程序通信。我怎么能嘲笑呢?
@Service
public class PlannerServiceImpl implements PlannerService {
private static final Logger LOG = LoggerFactory.getLogger(PlannerServiceImpl.class);
@Autowired
private RepositoryA repositoryA;
@Autowired
private RepositoryB repositoryB;
@Autowired
private ThirdPartyService thirdPartyService ;
}
如果我使用 Mock 注释,那么它仍然连接到外部应用程序,而不是返回模拟响应:
@Mock
ThirdPartyService thirdPartyService;
@Autowired
PlannerService plannerService;
如果我使用InjectMocks
注释,那么它会为RepositoryA
和RepositoryB
提供NullpointerException
.
@Mock
ThirdPartyService thirdPartyService;
@InjectMocks
PlannerService plannerService = newPlannerService();
我怎样才能模拟ThirdPartyService
并让 Spring 注入其他依赖项?
您可以使用 Whitebox
修改 Spring 注入的内容。或者,由于您使用的是 Spring,因此您也可以使用 ReflectionTestUtils.setField
依赖项之后,在单元测试运行之前,您可以使用 org.powermock.reflect.Whitebox
来修改 Spring 的注入。像这样的东西
Whitebox.setInternalState(plannerService, "thirdPartyService" thirdPartyService);
其中thirdPartyService
是你的模拟实例。
javadoc 在这里
或使用 Spring 的ReflectionTestUtils
:
ReflectionTestUtils.setField((plannerService, "thirdPartyService" thirdPartyService);
Java 文档在这里
这通常可以在您的"设置"方法中完成,
@Before
注释。您可以在PlannerService
类中使用 setter 方法
void setRepositoryA(RepositoryA repository) {
this.repositoryA = repository;
}
然后在测试中使用此方法提供RepositoryA
的模拟实现
或者,您可以在构造函数中@Inject存储库,然后在单元测试中调用构造函数,并将模拟作为参数。
@Autowiring
和@InejctMocks
肯定可以在测试用例中使用(注释在不同的实例字段上单独使用(。
确保您:
1( 在@Before
方法中启动模拟
@Before
public void before(){
MockitoAnnotations.initMocks(this);
}
2( 在@RunWith
类注解中使用SpringJUnit4ClassRunner.class