【问题标题】:Unable to load property from application.yml - Junit5无法从 application.yml 加载属性 - Junit5
【发布时间】:2021-12-29 22:41:59
【问题描述】:

我正在为从 application.yml 文件获取属性的组件方法编写一个 Junit 测试用例,当我运行 spring boot 应用程序时,此方法没有任何问题,但在运行 junit 测试用例时失败,以下是错误时我跑过 Junit:

java.lang.NullPointerException: Cannot invoke "org.springframework.core.env.Environment.getProperty(String)" because "this.environment" is null
    at com.ylm.cnpl.core.util.EnvUtil.getEnvValue(EnvUtil.java:86)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

Application.java

@SpringBootApplication
@ComponentScan(basePackages = {"com.ylm.cnpl.core"})
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

EnvUtil.java

@Component
public class EnvUtil {
    @Autowired
    private Environment environment;
    
    public String getEnvValue(String key){
        return environment.getProperty(key);
    }
}

EnvUtilTest.java

@SpringBootTest
public class EnvUtilTest {
    @Autowired
    private EnvUtil envUtil;
    @Mock
    Environment env;
    @Test
    public void getValueFromEnvConfigTest(){
        // THE BELOW LINE FIXED THE ISSUE!!!
        Mockito.when(env.getProperty(Mockito.any())).thenReturn("ADM");
        String envConfigValue = this.envUtil.getEnvValue("center.office.dept");
        assertNotNull(envConfigValue);
    }
}

我在我的测试课上尝试了以下选项,但没有运气,知道我在哪里错了吗?

  1. 在我的测试类中添加以下内容
@ComponentScan(basePackages = {"com.ylm.cnpl.core"})
  1. 尝试显式加载属性文件
@TestPropertySource(properties = { "spring.config.location=classpath:application.yml" })
  1. 尝试加载为 spring 配置文件,将 application.yml 重命名为 application-test.yml 并指定测试配置文件
@ActiveProfiles("test")

Project structure 这是我的 springboot 项目中包含的依赖项

<dependency>
    <groupId>com.ylm.cnpl.core</groupId>
    <artifactId>cnpl-common</artifactId>
    <version>0.0.1</version>
    <scope>compile</scope>
</dependency>

更新:

模拟环境显式工作

// THE BELOW LINE FIXED THE ISSUE!!!
Mockito.when(env.getProperty(Mockito.any())).thenReturn("ADM");

【问题讨论】:

    标签: spring spring-boot spring-mvc junit junit5


    【解决方案1】:

    您的 EnvUtil 类不是 Spring bean,@Bean 注释不适用于类型。由于EnvUtil 不是bean,Spring 无法将Environment bean 注入其中。

    尝试像这样将其更改为@Component:

    @Component
    public class EnvUtil {
        @Autowired
        private Environment environment;
        
        public String getEnvValue(String key){
            return environment.getProperty(key);
        }
    }
    

    【讨论】:

    • 我对 Component 也有同样的问题,它最初是组件而不是 bean 我已经更正了问题中的错字
    • 你的 application.yml 文件长什么样?
    • 感谢您将代码放在 gitgub 上的努力,我非常感谢。 Util 模块在一个通用框架中,并在我的 pom.xml 中用作参考,在 spring-boot 项目中使用的通用模块可能是问题所在?
    • 应该没问题;如果它与您扫描的 @ComponentScan(basePackages = {"com.ylm.cnpl.core"}) 位于同一(子)包中。
    【解决方案2】:

    确保您的 application.yml 位于 test/resources 文件夹中

    【讨论】:

    • 是的,它在测试/资源中
    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案3】:

    编辑:抱歉之前的回答,我误解了最初的问题,并认为您只是想从 application.yml 文件中提取一个属性来进行测试。

    因此,您正在为envUtil.getEnvValue() 方法编写单元测试。因此,您实际上不应在测试中调用 environment.getProperty() 方法,而应模拟 Environment 类并编写语句 when(environment.getProperty(anyString())).thenReturn("property");

    单元测试应该只测试特定方法而不是被调用的其他方法。

    【讨论】:

    • 您的建议中的 EnvUtil 组件在哪里?目的是测试获取属性的组件方法。
    猜你喜欢
    • 2020-03-07
    • 2022-01-22
    • 2019-11-23
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 2015-08-20
    • 2023-01-30
    • 1970-01-01
    相关资源
    最近更新 更多