spring 在单元测试中覆盖自动装配的 Bean
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28605833/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Overriding an Autowired Bean in Unit Tests
提问by samblake
Is there a simple way I can easily override an autowired bean in specific unit tests? There is only a single bean of every type in the compile classes so it's not a problem for autowiring in this case. The test classes would contain additional mocks. When running a unit test I'd simply like to specify an additional Configuration that says basically, while running this unit test use this mock instead of the standard bean.
有没有一种简单的方法可以在特定的单元测试中轻松覆盖自动装配的 bean?编译类中每种类型只有一个 bean,因此在这种情况下自动装配不是问题。测试类将包含额外的模拟。在运行单元测试时,我只想指定一个基本的附加配置,而运行此单元测试时使用此模拟而不是标准 bean。
Profiles seem a bit overkill for what I require and I'm not sure this would be achievable with the Primary annotation as different unit test could have different mocks.
配置文件对于我需要的东西似乎有点矫枉过正,我不确定这是否可以通过主注释实现,因为不同的单元测试可能有不同的模拟。
回答by teo
If you just simply want to provide a different bean in your tests, i think you don't need to use spring profiles or mockito.
如果您只是想在测试中提供不同的 bean,我认为您不需要使用 spring 配置文件或 mockito。
Just do the following:
只需执行以下操作:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { TestConfig.class })
public class MyTest
{
@Configuration
@Import(Application.class) // the actual configuration
public static class TestConfig
{
@Bean
public IMyService myService()
{
return new MockedMyService();
}
}
@Test
public void test()
{
....
}
}
NOTE: tested with spring boot 1.3.2 / spring 4.2.4
注意:使用弹簧靴 1.3.2 / 弹簧 4.2.4 进行测试
回答by Sergey Shcherbakov
In Spring Boot 1.4 there's a simple way for doing that:
在 Spring Boot 1.4 中,有一种简单的方法可以做到这一点:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { MyApplication.class })
public class MyTests {
@MockBean
private MyBeanClass myTestBean;
@Before
public void setup() {
...
when(myTestBean.doSomething()).thenReturn(someResult);
}
@Test
public void test() {
// MyBeanClass bean is replaced with myTestBean in the ApplicationContext here
}
}
回答by Israel Fernández
I had similar problem and I solved with a mix and I find this one more useful and reusable. I created a spring profile for the tests and a config class that overrides the beans I want to mock in a very simple way:
我有类似的问题,我用混合解决了,我发现这个更有用和可重用。我为测试创建了一个 spring 配置文件和一个配置类,它以一种非常简单的方式覆盖了我想模拟的 bean:
@Profile("test")
@Configuration
@Import(ApplicationConfiguration.class)
public class ConfigurationTests {
@MockBean
private Producer kafkaProducer;
@MockBean
private SlackNotifier slackNotifier;
}
By doing that I can @Autowire those mock beans and use mockito to verify on them. Main advantage is that now all tests seamlessly get the mock beans without any per-test change. Tested with:
通过这样做,我可以@Autowire 那些模拟 bean 并使用 mockito 来验证它们。主要优点是现在所有测试都可以无缝地获取模拟 bean,而无需对每个测试进行任何更改。测试:
spring boot 1.4.2
弹簧靴 1.4.2
回答by Eddú Meléndez
You should use spring profiles in order to know what kind of bean you want to use in different contexts.
您应该使用 spring 配置文件来了解您想在不同的上下文中使用哪种 bean。
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html
回答by awgtek
As mats.nowak commented, @ContextConfiguration
is useful for this.
正如 mats.nowak 评论的那样,@ContextConfiguration
对此很有用。
Say a parent test class is like:
说一个父测试类是这样的:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/some-dao-stuff.xml"
,"classpath:spring/some-rest-stuff.xml"
,"classpath:spring/some-common-stuff.xml"
,"classpath:spring/some-aop-stuff.xml"
,"classpath:spring/some-logging-stuff.xml"
,"classpath:spring/some-services-etc.xml"
})
public class MyCompaniesBigTestSpringConfig {
...
Create a child test class:
创建一个子测试类:
package x.y.z;
@ContextConfiguration
public class MyOneOffTest extends MyCompaniesBigTestSpringConfig {
...
and put in src/test/resources/x/y/z/MyOneOffTest-context.xml
并放入 src/test/resources/x/y/z/MyOneOffTest-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="widgetsService" class="com.mycompany.mydept.myservice.WidgetsService" primary="true" />
</beans>
That widgetsService
bean will override (take the place of) the bean defined in the main config xml (or Java config). See about inheritLocationsAlso Note the default -context.xml file. Example of that here.
Update: I had to add primary="true"
, apparently it's needed.
该widgetsService
bean 将覆盖(代替)在主配置 xml(或 Java 配置)中定义的 bean。请参阅inheritLocations另请注意默认的-context.xml 文件。这里的例子。更新:我不得不添加primary="true"
,显然是需要的。