如何解决此 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)?

如何解决在类路径中定义名称为“configurationPropertiesBeans”的 bean 创建错误?

如何在不覆盖 Spring Boot 使用的情况下定义自定义 ObjectMapper bean