java - 为什么组件扫描不适用于 Spring Boot 单元测试?

标签 java spring unit-testing spring-boot integration-testing

服务类FooServiceImpl@Service 注释又名 @Component这使它有资格进行 Autowiring 。为什么在单元测试期间没有选择和 Autowiring 这个类?

@Service
public class FooServiceImpl implements FooService {
    @Override
    public String reverse(String bar) {
        return new StringBuilder(bar).reverse().toString();
    }
}

@RunWith(SpringRunner.class)
//@SpringBootTest
public class FooServiceTest {
    @Autowired
    private FooService fooService;
    @Test
    public void reverseStringShouldReverseAnyString() {
        String reverse = fooService.reverse("hello");
        assertThat(reverse).isEqualTo("olleh");
    }
}

测试未能加载应用程序上下文,
2018-02-08T10:58:42,385 INFO    Neither @ContextConfiguration nor @ContextHierarchy found for test class [io.github.thenilesh.service.impl.FooServiceTest], using DelegatingSmartContextLoader
2018-02-08T10:58:42,393 INFO    Could not detect default resource locations for test class [io.github.thenilesh.service.impl.FooServiceTest]: no resource found for suffixes {-context.xml}.
2018-02-08T10:58:42,394 INFO    Could not detect default configuration classes for test class [io.github.thenilesh.service.impl.FooServiceTest]: FooServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
2018-02-08T10:58:42,432 INFO    Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, (...)org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
2018-02-08T10:58:42,448 INFO    Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@f0ea28, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@16efaab,(...)org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@9604d9]
2018-02-08T10:58:42,521 INFO    Refreshing org.springframework.context.support.GenericApplicationContext@173f9fc: startup date [Thu Feb 08 10:58:42 IST 2018]; root of context hierarchy
2018-02-08T10:58:42,606 INFO    JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2018-02-08T10:58:42,666 ERROR    Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@19aaa5] to prepare test instance [io.github.thenilesh.service.impl.FooServiceTest@57f43]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'io.github.thenilesh.service.impl.FooServiceTest': Unsatisfied dependency expressed through field 'fooService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'io.github.thenilesh.service.FooService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    . . . 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) [.cp/:?]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'io.github.thenilesh.service.FooService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    ... 28 more
2018-02-08T10:58:42,698 INFO    Closing org.springframework.context.support.GenericApplicationContext@173f9fc: startup date [Thu Feb 08 10:58:42 IST 2018]; root of context hierarchy

Full stack trace

如果测试类用 @SpringBootTest 注释然后它创建整个应用程序上下文,包括数据库连接和许多不相关的 bean,这些 bean 显然不需要这个单元测试(它不会是单元测试!)。所期望的是,只有 bean 在FooService依赖应该被实例化,除了被模拟的,用 @MockBean .

最佳答案

您应该使用 @SpringBootTest(classes=FooServiceImpl.class) .

正如在 Annotation Type SpringBootTest 上提到的:

public abstract Class[] classes

The annotated classes to use for loading an ApplicationContext. Can also be specified using @ContextConfiguration(classes=...). If no explicit classes are defined the test will look for nested @Configuration classes, before falling back to a SpringBootConfiguration search.

Returns: the annotated classes used to load the application context See Also: ContextConfiguration.classes()

Default: {}



这将只加载必要的类。如果不指定,它可能会加载数据库配置和其他会使您的测试变慢的东西。

另一方面,如果你真的想要单元测试,你可以在没有 Spring 的情况下测试这段代码 - 然后 @RunWith(SpringRunner.class)@SpringBootTest注释不是必需的。您可以测试 FooServiceImpl实例。如果您有 Autowired/injected 属性或服务,您可以通过 setter、构造函数或模拟来设置它们 Mockito .

关于java - 为什么组件扫描不适用于 Spring Boot 单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48679637/

相关文章:

java - java套接字的问题

spring - 用 Spring 调试 Jackson

java - 我正在使用 SpringBoot 和 Jquery 以及 Ajax 编写一个 CRUD 应用程序。我收到以下异常

java - 正在启动 Spring 应用程序地址已在使用中

c++ - 我可以使用 google mocks 来检查方法参数而不提前设置期望值吗?

angularjs - Angular 单元测试 : Argument 'fn' is not a function, 得到对象

java - 特殊领域的正则表达式重音字符

java - 在java中使用Boxable和PDFBox将大表渲染为pdf文件

Java:如何故意使 Jenkins 构建失败?

unit-testing - 单元测试概率