如何解决此 bean 定义覆盖?
Posted
技术标签:
【中文标题】如何解决此 bean 定义覆盖?【英文标题】:How do I resolve this bean defninition override? 【发布时间】:2020-01-25 22:07:55 【问题描述】:我已经从 Spring Boot 1.5 升级到 Spring Boot 2.1.8。我有一些测试有效,但现在失败了。 我还在 2.9 版本中使用了 maven-surefire 插件,它工作正常,但我也将它升级到 2.22.0,如果这很重要的话。
@ExtendWith(SpringExtension.class)
@WebMvcTest(value = ElementController.class, secure = false)
@ContextConfiguration(classes = TestSite1Config.class)
public class ElementControllerSite1IT
@Autowired
protected MockMvc mvc;
@MockBean
ElementService elementService;
@BeforeEach
public void setup()
when(elementService.getElementTable( ... )) //skipping args for brevity
.thenReturn(new ElementTable());
@Configuration
public static class TestSite1Config
@Bean
@Autowired
public ElementController elementController(final ElementService elementService)
return new ElementController(elementService, new ElementControllerProperties(DeploymentLocation.SITE1));
@Test
public void failSite1ValidationWithoutId() throws Exception
ElementParameters params = getParams(false);
mvc.perform(post("/element")
.contentType(JSON)
.andExpect(status().isBadRequest());
//more tests, but doesn't matter.
还有一个类似上面的类,但是将 Site1 替换为 Site2。
还有一个 ElementController & Service 类。
我得到了这个例外:
Caused by BeanDefinitionOverrideException: Invalid bean definition with name 'elementController' defined in class path resource [ui/v2/web/ElementControllerSite1IT$TestSite1Config.class]: Cannot register bean definition [Root bean: class [null]; ... defined in class path resource [ui/v2/web/ElementControllerSite1ITConfig.class] for bean 'elementController': There is already [Generic bean: class [ui.v2.web.ElementController]; .. defined in file [...ui/v2/web/ElementController.class]] bound.
我没有编写测试,它是我继承的代码,在我刚刚开始使用的代码库中。
【问题讨论】:
一开始就应该运行失败。删除TestSite1Config, or at least remove the controller and only return the
ElementControllerProperties. Spring will take care of injecting the right properties in the
ElementController`,这就是@WebMvcTest
中的ElementController
。
为什么会失败?之前,它会自动覆盖 elementController bean(用于真实类),并使用此处创建的模拟对象。你能解释一下,或者给我一个链接到可能会阐明这一点的东西吗?我尝试删除 TestSite1Config 并且情况更糟。 ContextConfiguration 注释中会包含什么内容?
正如我在最初的评论中提到的,您应该只使用 ElementControllerProperties
进行配置。 Spring 测试部分将负责创建 ElementController
,因为这是 @WebMvcTest
负责的。
我还是有点困惑。有一些东西是“配置”。你是说我的 TestSite1Config 应该只返回 ElementControllerProperties 吗?所以:<code> @Configuration public static class TestSite1Config @Bean public ElementControllerProperties elementControllerProperties() return new ElementControllerProperties(DeploymentLocation.SITE1); </code>
这样做,在我的测试中,无论我扔给它什么,我都会得到 404,这至少意味着它正在连接一些东西?为什么这不像代码那样格式化?对不起 =(
这就是它应该返回的内容。这与模拟服务一起应该足以创建ElementController
。虽然 404 很奇怪,但你能分享一下日志吗?
【参考方案1】:
你可以试试@TestPropertySource(properties ="..."
:
@ExtendWith(SpringExtension.class)
@WebMvcTest(value = ElementController.class, secure = false)
@ContextConfiguration(classes = TestSite1Config.class)
@TestPropertySource(properties = "spring.main.allow-bean-definition-overriding=true", "local.server.port=7777")
public class ElementControllerSite1IT
...
【讨论】:
我试过了,还是不行。我得到与上面相同的错误。 我刚刚在本地重现了这个错误,我的配置工作正常。您是否按原样尝试过,使用适当的值(没有 test-application.properties)? 是的,除了在我的道具文件中之外,我还尝试了您提供的硬编码值。没有骰子。也许我需要更改版本的 pom 中还有其他内容?您可以发布您的 pom.xml 以进行构建吗? 我已将工作示例提交到 github。你可以克隆它并检查:github.com/ivan333m/mock.git。看看github.com/ivan333m/mock/blob/master/demo/src/test/java/com/…。 RestTemplate 被覆盖【参考方案2】:将spring.main.allow-bean-definition-overriding=true
添加到application.properties
【讨论】:
我尝试使用@TestPropertySource(在我的test-application.properties)文件中添加它并作为直接注入,但它没有工作。我还想了解 为什么 它不能按编码工作,而不仅仅是撤消 Spring 对 bean 覆盖行为方式所做的更改。【参考方案3】:解决了这个问题:(对于任何偶然发现这个问题的人)
@ExtendWith(SpringExtension.class)
@AutoConfigureMockMvc
@WebMvcTest
@ContextConfiguration(classes = ElementController.class,TestSite1Config.class)
public class ElementControllerSite1IT
@Autowired
private MockMvc mvc;
...
@Configruation
public static class TestSite1Config
@Bean
@Primary
public ElementControllerProperties elementControllerProperties() return ...
...
【讨论】:
它搞砸了(我认为其他人添加了一些将事情搞砸的代码)。我最终使用了配置文件,因为这样更干净、更有效(并将其他测试与这些更改隔离开来)。看到这个项目:***.com/questions/39041542/…以上是关于如何解决此 bean 定义覆盖?的主要内容,如果未能解决你的问题,请参考以下文章
如何解决此错误“('HttpClient Function(SecurityContext)')不是'HttpOverrides.createHttpClient'的有效覆盖”
如何解决在类路径资源中定义名称为“entityManagerFactory”的 bean 创建错误?
如何解决此问题:LoginController 中构造函数的参数 0 需要找不到类型为“OktaOAuth2Properties”的 bean
如何解决此MarkerCluster签入/签出错误(传单salesforce)?