我正在使用 springockito-annotations 1.0.9
进行集成测试。
我有以下 Controller :
@Autowired
public Controller(
@Qualifier("passwordService ") PasswordService passwordService ,
@Qualifier("validator") Validator validator,
@Qualifier("reportService") ReportService reportService,
DateCalculator dateCalculator,
Accessor accessor){
this.passwordService = passwordService;
this.validator = validator;
this.reportService = reportService;
this.dateCalculator = dateCalculator;
this.accessor = accessor;
}
在测试中,我将使用 @ReplaceWithMock 注释从上下文中替换 bean。
但不幸的是,它仅适用于没有@Qualifier 注释的依赖项。
也就是说,我的测试看起来像这样:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(loader = SpringockitoAnnotatedContextLoader.class, classes = {TestContext.class})
public class ControllerTest {
@Autowired
@ReplaceWithMock
private PasswordService passwordService ;
@Autowired
@ReplaceWithMock
private Validator validator;
@Autowired
@ReplaceWithMock
private ReportService reportService;
@Autowired
@ReplaceWithMock
private DateCalculator dateCalculator;
@Autowired
@ReplaceWithMock
private Accessor accessor;
@Autowired
private Controller controller;
}
在最后一种情况下,在初始化上下文后,只有 DateCalculator 和 Accessor bean 正确替换为所需的模拟,但另一个 bean 从主上下文 Autowiring 为普通 bean。
调试后发现QualifierAnnotationAutowireCandidateResolver 无法正确识别bean。在下面从 229 开始的行中:
RootBeanDefinition bd = (RootBeanDefinition) bdHolder.getBeanDefinition();
AutowireCandidateQualifier qualifier = bd.getQualifier(type.getName());
Spring 试图从mocked dependency 中提取限定符,但它是空的。
很高兴知道如何使用 @Qualifier 正确替换依赖项以模拟对象。
最佳答案
编辑:添加了指向白盒替代品的链接,它在更高版本的 Mockito 中消失了
可以使用 mockitos @Mock
和 @InjectMocks
将东西注入(inject)到您要测试的类中,如另一篇文章中所建议的。我曾经认为这是测试 spring 托管 beans 的好方法,但现在我认为这是有问题的;如果
由 @InjectMocks
完成的注入(inject)失败,它会悄无声息地进行,而且您不知道为什么。创建测试时它是可以管理的,但是当你有一些像这样的测试时,由于一个小的无意的小错误,几个测试开始失败并出现空指针
更改某人所做的应用程序上下文,或者在引入轻微异常或类似情况的合并之后,它变得比需要的更困惑。
我建议您改用 mockitos Whitebox
,请参阅下面的示例。有了它,你可以明确地告诉你想用什么对象“注入(inject)”哪个字段,在复杂的情况下,你可以注入(inject)多个对象。 Mockito 在注入(inject)时使用 Whitebox(但会吞下所有异常)。
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration( /*something that fits your setup*/ )
public class ControllerTest {
@Autowired
private PasswordService passwordService ;
@Autowired
private Validator validator;
@Autowired
private ReportService reportService;
@Autowired
private Controller testObject;
@Before
public void setupBefore() {
//Since this "injection" is done manually the qualifiers does not matter
Whitebox.setInternalState(testObject, "passwordService", passwordService);
Whitebox.setInternalState(testObject, "validator", validator);
Whitebox.setInternalState(testObject, "reportService", reportService);
}
@Test
public void testSomething() {
}
}
如果您正在进行常规单元测试,Whitebox
可以帮助您在没有 spring 上下文的情况下进行测试。我可以强烈推荐这种方法(但它有点偏离主题,我不会发布我在注意到您正在进行集成测试之前写的示例;))。
编辑:如果您使用的是更高版本的 Mockito,您会注意到 Whitebox 已经消失,那么该怎么办呢? 我遇到了这种情况,并寻求建议:What do I use instead of Whitebox in Mockito 2.2 to set fields?
关于java - @ReplaceWithMock 与 @Qualifier,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26032594/