【问题标题】:Spring controller testing with dependencies failing依赖项失败的 Spring 控制器测试
【发布时间】:2018-11-22 18:43:37
【问题描述】:

我有以下控制器类:

@Controller
public class HelloController {

    private final HelloService service;

    public HelloController(HelloService service) {
        this.service = service;
    }

    @RequestMapping("/hello")
    public @ResponseBody String greeting() {
        return service.greet();
    }

}

如您所见,它接受依赖项。这一切都在服务器上运行良好。但是,在测试时,它失败了:

@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class WebLayerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void shouldReturnDefaultMessage() throws Exception {
    this.mockMvc.perform(get("/hello")).andDo(print()).andExpect(status().isOk())
                .andExpect(content().string(containsString("Hello World")));
    }
}

下面是target/surefire-reports/中日志文件的输出

-------------------------------------------------------------------------------
Test set: biz.martyn.footy.WebLayerTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.278 s <<< FAILURE! - in biz.martyn.footy.WebLayerTest
shouldReturnDefaultMessage(biz.martyn.footy.WebLayerTest)  Time elapsed: 0.005 s  <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloController' defined in file [/home/martyn/eclipse-workspace/Footy/target/classes/biz/martyn/footy/controller/HelloController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'biz.martyn.footy.service.HelloService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'biz.martyn.footy.service.HelloService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

我知道@MockBean 允许我创建依赖项的模拟,但在我不想模拟它的情况下?在这里,我很高兴能够正常使用真正的依赖实例。或者,是因为我只测试 web 层,它没有像运行完整应用程序时那样实例化控制器?

更新

我还尝试了@Autowired 注入而不是构造函数。我的应用程序有效,因此将依赖项引入控制器,但测试失败。以下是更新后的控制器:

@Controller
public class HelloController {

    @Autowired
    private HelloService service;

    @RequestMapping("/hello")
    public @ResponseBody String greeting() {
        return service.greet();
    }

}

【问题讨论】:

  • 我假设应用程序的某个地方有一个 Spring 上下文,它将 HellowService 连接到 HelloController。测试执行中如何加载 Spring 上下文?
  • 那不是MockMvc吗?
  • 也许,如果你已经 @Autowired 服务到控制器,通过将该注释添加到构造函数或属性?我不认为 SPring 会在没有明确声明的情况下为您自动装配东西,无论是在代码中通过注释还是通过 XML 上下文配置文件......
  • 不,如果你只有一个构造函数,Spring 不需要任何 Autowired 注解。默认情况下,它会在该构造函数中自动装配依赖项。所以你的代码完全没问题。如果你想测试整个事情,而不仅仅是带有模拟服务层的 web 层,那么不要使用 WebMvcTest。使用这个:docs.spring.io/spring-boot/docs/current/reference/htmlsingle/…
  • @JBNizet 你是对的 :-) - 看起来像是在 4.3 中添加到 Spring 的功能:baeldung.com/constructor-injection-in-spring

标签: java spring-mvc spring-test-mvc


【解决方案1】:

@WebMvcTest 将禁用完全自动配置,而是仅应用与 MVC 测试相关的配置(即 @Controller@ControllerAdvice@JsonComponent、Converter/GenericConverter、Filter、WebMvcConfigurer 和 HandlerMethodArgumentResolver bean,但不是 @Component , @Service or @Repository beans,所以你必须使用 @MockBean 来满足依赖。

【讨论】:

    猜你喜欢
    • 2017-06-05
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 2018-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多