java - @ReplaceWithMock 与 @Qualifier

标签 java unit-testing spring-mvc integration-testing springockito

我正在使用 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/

相关文章:

java - 与 mediaUrl 的 URL 连接失败,收到错误消息意外的状态行 : ICY 200 OK on KitKat

c# - 对 .Net core 3.1 后台服务进行单元测试时,无法解析 IConfiguration

javascript - Protractor 已弃用 getLocationAbsUr

unit-testing - 在 OCaml 中使用 OUnit 模块 - 未绑定(bind)模块 OUnit 错误

java - 检测未初始化对象的类型

java - 将文件保存为 lob 还是 OS 文件?

java - 在 Spring 过滤器链中的 session 管理过滤器中获取 Firewalledrequest ClasscastException

java - 如何使用spring mvc在浏览器中下载文件?

java - OSGI Architecture 和 Maven 多模块项目有什么区别?

java - Spring框架上的多线程(或异步)计算