为什么Spring @Qualifier不适用于Spock和Spring Boot

时间:2015-04-28 14:13:24

标签: java spring testing spring-boot spock

我试图在Spock中为控制器编写测试。

@ContextConfiguration(loader = SpringApplicationContextLoader.class,
    classes = [Application.class, CreateUserControllerTest.class])
@WebAppConfiguration
@Configuration
class CreateUserControllerTest extends Specification {

    @Autowired
    @Qualifier("ble")
    PasswordEncryptor passwordEncryptor

    @Autowired
    UserRepository userRepository

    @Autowired
    WebApplicationContext context

    @Autowired
    CreateUserController testedInstance

    def "Injection works"() {
        expect:
        testedInstance instanceof CreateUserController
        userRepository != null
    }

    @Bean
    public UserRepository userRepository() {
        return Mock(UserRepository.class)
    }

    @Bean(name = "ble")
    PasswordEncryptor passwordEncryptor() {
        return Mock(PasswordEncryptor)
    }

}

应用程序类只是Spring Boot最简单的配置(启用自动扫描)。它提供了一个带PasswordEncryptor。我想用我的bean替换这个bean来提供模拟。

但不幸的是,Spring抛出NoUniqueBeanDefinitionException:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.jasypt.util.password.PasswordEncryptor] is defined: expected single matching bean but found 2: provide,ble
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 54 more

@Qualifier注释似乎根本不起作用。我该怎么办?

修改

问题不在CreateUserControllerTest,而在于CreateUserController

public class CreateUserController {
    @Autowired
    private PasswordEncryptor encryptor;
}

没有@Qualifier注释,因此Spring不知道应该注入哪个bean。不幸的是,我不知道如何让Spring通过本地配置从Application替换PasswordEncryptor bean。

1 个答案:

答案 0 :(得分:1)

@Qualifier用于连接bean的特定实例,如果您有多个相同接口的实现。

但是你仍然需要在spring上下文中为每个bean设置一个'UNIQUE'名称。

所以你试图注册两个名为“passwordEncryptor”的bean。一个在您的测试中,看起来另一个在您的实际代码“Application.class”中。

如果您想模拟'PasswordEncryptor',请使用@Mock@Spy。 (或)如果要避免错误,请更改方法的名称以避免实例名称冲突。

@Mock
private PasswordEncryptor passwordEncryptor;

or

@Spy
private PasswordEncryptor passwordEncryptor;

<强> 修改

该错误的另一种可能性是您的代码中某处为“@Autowired”定义了passwordEncryptor而没有@Qualifier标记,

但是

你定义了两个@Bean(name="...") passwordEncryptor个实例,因此Spring上下文很难选择哪一个'自动连接'字段。