【问题标题】:How do I resolve this bean defninition override?如何解决此 bean 定义覆盖?
【发布时间】: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 很奇怪,但你能分享一下日志吗?

标签: spring spring-boot testing


【解决方案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 ... }
  }
  ...
}

【讨论】:

  • 它搞砸了(我认为其他人添加了一些将事情搞砸的代码)。我最终使用了配置文件,因为这样更干净、更有效(并将其他测试与这些更改隔离开来)。看到这个项目:stackoverflow.com/questions/39041542/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-18
  • 2018-10-18
  • 1970-01-01
  • 1970-01-01
  • 2016-06-08
  • 2020-07-08
  • 2013-10-02
相关资源
最近更新 更多