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

Posted

技术标签:

【中文标题】java.lang.IllegalArgumentException:无法实例化接口 org.springframework.context.ApplicationListener【英文标题】:java.lang.IllegalArgumentException: Cannot instantiate interface org.springframework.context.ApplicationListener 【发布时间】:2021-12-21 19:44:22 【问题描述】:

我是 Mockito 的新手,我正在尝试为 Main Class 编写单元测试,面临一些无法实例化 bean 的问题。请任何人帮我解决这个问题。如果有人给我建议如何在模拟中为下面的课程编写单元测试。

主类

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);
    

在这里测试类:

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$2.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$1.call(InvocationFactory.java:55)
    at org.mockito.internal.invocation.RealMethod$FromCallable$1.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)

【问题讨论】:

【参考方案1】:

为您的 Spring Boot 入口点类 ObsDocumentApplication 编写单元测试几乎没有价值,因为您最终会得到几乎完全相同的实现副本。

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

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

您可以为此使用the @SpringBootTest annotation。

【讨论】:

以上是关于java.lang.IllegalArgumentException:无法实例化接口 org.springframework.context.ApplicationListener的主要内容,如果未能解决你的问题,请参考以下文章

IllegalArgumentException:此 NavController 未知导航目的地 xxx