java.lang.IllegalArgumentException: 无法实例化接口 org.springframework.context.ApplicationListener

java.lang.IllegalArgumentException: Cannot instantiate interface org.springframework.context.ApplicationListener

我是 Mockito 的新手,我正在尝试为 Main Class 编写单元测试,但遇到一些无法实例化 bean 的问题。请任何人帮我解决这个问题。如果有人给我建议如何在 mockito 中为以下 class.

编写单元测试

主要class

import com.ab.obs.spring.ObsSpringBootApplicationForCloud;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import com.ab.obs.config.EncryptDecryptUtilConfig;
import com.ab.csl.retail.core.config.HikariDataSourceConfig;
import org.springframework.context.annotation.Import;

@Import({EncryptDecryptUtilConfig.class, HikariDataSourceConfig.class})
@SpringBootApplication
@EnableAspectJAutoProxy
public class ObsDocumentApplication extends SpringBootServletInitializer {


    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        ObsSpringBootApplicationForCloud.initBase(application, "csl-svc-obs-test");
        return application;
    }

    public static void main(String[] args) {
        SpringApplicationBuilder application = new SpringApplicationBuilder();
        ObsSpringBootApplicationForCloud.initBase(application, "csl-svc-obs-test");
        application.sources(ObsDocumentApplication.class)
                .run(args);
    }
}

在此处测试 Class:

import com.ab.obs.spring.ObsSpringBootApplicationForCloud;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.boot.builder.SpringApplicationBuilder;
import static org.powermock.api.mockito.PowerMockito.*;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ObsDocumentApplication.class, ObsSpringBootApplicationForCloud.class})
public class ObsDocumentApplicationTest {
    @Mock
    private SpringApplicationBuilder applicationBuilder;

    @Before
    public void setUp() throws  Exception{
        PowerMockito.spy(ObsDocumentApplication.class);
        PowerMockito.spy(ObsSpringBootApplicationForCloud.class);
        applicationBuilder = mock(SpringApplicationBuilder.class);
    }

    @Test
    public void testMainClass() {
        ObsDocumentApplication.main(new String[] {});
    }

}

错误日志:

java.lang.IllegalArgumentException: Cannot instantiate interface org.springframework.context.ApplicationListener : org.springframework.cloud.function.compiler.config.FunctionProxyApplicationListener

    at org.springframework.boot.SpringApplication.createSpringFactoriesInstances(SpringApplication.java:467)
    at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:449)
    at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:442)
    at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:285)
    at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:264)
    at org.springframework.boot.builder.SpringApplicationBuilder.createSpringApplication(SpringApplicationBuilder.java:109)
    at org.springframework.boot.builder.SpringApplicationBuilder.<init>(SpringApplicationBuilder.java:97)
    at com.sc.obs.ObsDocumentApplication.main(ObsDocumentApplication.java:25)
    at com.sc.obs.ObsDocumentApplicationTest.testMainClass(ObsDocumentApplicationTest.java:31)
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:89)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cloud.function.compiler.config.FunctionProxyApplicationListener]: Constructor threw exception; nested exception is java.lang.ClassCastException: class com.sun.tools.javac.api.JavacTool
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:225)
    at org.springframework.boot.SpringApplication.createSpringFactoriesInstances(SpringApplication.java:463)
    at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:449)
    at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:442)
    at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:285)
    at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:264)
    at org.springframework.boot.builder.SpringApplicationBuilder.createSpringApplication(SpringApplicationBuilder.java:109)
    at org.springframework.boot.builder.SpringApplicationBuilder.<init>(SpringApplicationBuilder.java:97)
    at com.sc.obs.ObsDocumentApplication.main(ObsDocumentApplication.java:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.powermock.api.mockito.invocation.InvocationFactory.call(InvocationFactory.java:55)
    at org.mockito.internal.invocation.RealMethod$FromCallable.call(RealMethod.java:40)
    at org.mockito.internal.invocation.RealMethod$FromBehavior.invoke(RealMethod.java:62)
    at org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:141)
    at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:44)
    at org.mockito.Answers.answer(Answers.java:98)
    at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:106)
    at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
    at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:33)
    at org.powermock.api.mockito.invocation.MockHandlerAdaptor.performIntercept(MockHandlerAdaptor.java:64)
    at org.powermock.api.mockito.invocation.MockitoMethodInvocationControl.invoke(MockitoMethodInvocationControl.java:94)
    at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:186)
    at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:168)
    at org.powermock.core.MockGateway.methodCall(MockGateway.java:145)
    at com.sc.obs.ObsDocumentApplication.main(ObsDocumentApplication.java)
    at com.sc.obs.ObsDocumentApplicationTest.testMainClass(ObsDocumentApplicationTest.java:31)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)

为您的 Spring 引导入口点 class ObsDocumentApplication 编写单元测试没有什么价值,因为您最终得到的是您的实现的几乎完全相同的副本。

此类测试只能验证您的模拟设置是否与您的实现相匹配。对您的实现的任何更改很可能会导致单元测试失败,因为需要调整存根设置。

更好的方法是编写一个集成测试,确保您的 Spring ApplicationContext 可以启动(这将隐式验证您的 ObsDocumentApplication)。

您可以使用 the @SpringBootTest annotation 来达到这个目的。