Mockito:如何在spring bean中部分模拟字段依赖项

时间:2018-01-13 14:07:28

标签: java spring unit-testing mockito

我有一个具有多个字段依赖关系的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注释,则会为NullpointerExceptionRepositoryA提供RepositoryB

@Mock
ThirdPartyService thirdPartyService;

@InjectMocks 
PlannerService plannerService = newPlannerService();

我怎样才能模拟ThirdPartyService并让Spring注入其他依赖项?

3 个答案:

答案 0 :(得分:0)

您可以在PlannerService课程中使用setter方法

void  setRepositoryA(RepositoryA repository) {
    this.repositoryA = repository;
}

然后在测试中使用此方法提供RepositoryA

的模拟实现

或者您可以在构造函数中@Inject存储库,然后在您的单元测试中调用构造函数,将mocks作为参数。

答案 1 :(得分:0)

您可以使用Whitebox修改Spring注入的内容。或者,由于您使用的是Spring,因此您也可以使用ReflectionTestUtils.setField

在Spring注入依赖项之后,在运行单元测试之前,您可以使用org.powermock.reflect.Whitebox来修改Spring的注入。像这样的东西

Whitebox.setInternalState(plannerService, "thirdPartyService" thirdPartyService);

thirdPartyService是您的模拟实例。

javadoc here

或使用Spring的ReflectionTestUtils

ReflectionTestUtils.setField((plannerService, "thirdPartyService" thirdPartyService);

java doc here

这通常可以在您的“设置”方法中完成,该方法使用@Before注释。

答案 2 :(得分:-1)

@Autowiring@InejctMocks可以在测试用例中使用(注释在不同的实例字段中单独使用)。

请确保:

1)使用@Before方法启动Mockito模拟:

@Before
public void before(){
 MockitoAnnotations.initMocks(this);
}

2)SpringJUnit4ClassRunner.class班级注释中使用@RunWith