【问题标题】:How to mock bean and avoiding NoUniqueBeanDefinitionException如何模拟 bean 并避免 NoUniqueBeanDefinitionException
【发布时间】:2016-04-23 00:38:08
【问题描述】:

我有基于 SpringMVC 的 webApplication,所有 bean 都通过 注解 进行定义。今天我尝试为我的控制器编写测试。我放了第一个并尝试模拟此控制器中使用的服务。所有这一切我都是通过以下方式完成的:

1) 为测试创建上下文文件clientControllerTest-context.xml

<import resource="classpath:spring-context.xml" />

<bean id="ConnectionDB" name="ConnectionDB" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="biz.podoliako.carwash.services.impl.ConnectDB" />
</bean>

其中 spring-context.xml 是我的 webApplication 中使用的主要上下文文件(包括有关 real ConnectionDB bean 的信息)

2)使用以下配置创建测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:controllers/clientControllerTest-context.xml"})
@WebAppConfiguration

运行测试时,NoUniqueBeanDefinitionException 异常被捕获。我希望 spring 覆盖 bean ConnectionDB 但实际上它找到了 2 个具有同一个名称的 bean,并且 spring 无法选择必须使用哪一个。

请解释我如何使用我的主要弹簧上下文并模拟其中一个 bean 进行测试并避免 NoUniqueBeanDefinitionException(如果它可能是原因的话)。

注意:我认为使用所有测试配置创建上下文是一个坏主意,因此我尝试使用我的主要 spring-context。

【问题讨论】:

    标签: java spring spring-mvc


    【解决方案1】:

    您可以为您的 Spring 应用程序定义 配置文件,并将您的 @Configuration 类或 @Bean 方法(或者甚至您的自定义元注释,如果您使用任何)绑定到命名配置文件,甚至是多个个人资料,如果你想。然后,您可以定义名称为 testdevelopmentproduction 或您想到的任何自定义场景的配置文件,并根据当前活动的配置文件将您的 bean 注册到您的 Spring 上下文。

    像这样为testanotherTest 配置文件定义你的bean:

    @Configuration
    @Profile({"test", "anotherTest"})
    public class SomeConfig {...}
    

    或者在 xml 文件中:

    ...
    <beans profile="test, anotherTest">
        <bean .../>
    </beans>
    ...
    

    以类似的方式定义您的 production 受限 bean,以避免配置文件中的 bean 冲突。然后,在您的 JUnit 测试类上使用 @ActiveProfiles 注释来指明您希望在运行测试时激活哪些配置文件:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(...)
    @ActiveProfiles({"test", "anotherTest"})
    

    如果您想以编程方式执行此操作,请参阅其他问题 Default profile in Spring 3.1,了解如何在 web 应用或 org.springframework.core.env.Environment 的 javadoc 中默认激活配置文件。

    【讨论】:

    • 我更改了我的 clientControllerTest-context.xml (模拟 bean 被 包裹,并在我的测试中添加以下注释:@ActiveProfiles(profiles = {"test"} ). 但这不是问题,我看到了同样的异常。可能是因为我没有定义默认配置文件而发生的?但是如何为通过注释定义的 bean 设置配置文件?
    • 您已将测试上下文 bean 定义为仅在“test”配置文件处于活动状态时才处于活动状态,然后为您的 JUnit 测试激活“test”配置文件。但是你的应用程序上下文中仍然有你的“真正的 ConnectionDB bean”,我猜你还没有限制到配置文件。所以你得到了两个具有相同接口或名称的 bean,而 Spring 无法决定在自动装配中使用哪一个。您需要将您的“真正的 ConnectionDB bean”限制为另一个配置文件(production 也许?)并在您的 Web 应用程序上下文中激活该配置文件,如我上一段中链接的问题中所示。
    猜你喜欢
    • 1970-01-01
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 2019-12-15
    • 1970-01-01
    • 2018-05-09
    • 2016-11-21
    相关资源
    最近更新 更多