当前位置: 首页 > 知识库问答 >
问题:

添加junit测试时,Spring boot应用程序无法启动

柯天宇
2023-03-14

我正在尝试将测试添加到我的Spring Boot应用程序,但当我这样做时,应用程序无法启动。

我有一个自定义的jwt授权类来验证jwt,我不确定这是否会导致任何问题?


@Component
public class JwtCustomValidator {

    private static final Logger logger = LoggerFactory.getLogger(LogDeletionJob.class);

    private static final String TAG = "JwtCustomValidator";

    public void validateAudience(Jwt jwt) throws Exception {
        //System.out.println("validate audience JWT AUDIENCE: " + jwt.getAudience().toString());
        if (!jwt.getAudience().contains(System.getenv("oauthAudience"))) {
            //System.out.println("\nAUDIENCE NOT AUTHORIZED!\n");
            logger.warn(TAG, "AUDIENCE NOT AUTHORIZED!" + jwt.getAudience());
            throw new Exception("wrong audience");
        }
        logger.info(TAG, "audience validated");
    }

    public void validateRole(final Jwt jwt, final String role) throws Exception {
        //System.out.println("validate roles JWT ROLES: " + jwt.getClaim("roles").toString());
        if (!((List<String>) jwt.getClaim("roles")).contains(role)) {
            //System.out.println("\nROLE NOT AUTHORIZED!\n");
            logger.warn(TAG, "ROLE NOT AUTHORIZED!" + jwt.getClaim("roles").toString());
            throw new Exception("Not sufficient role, UnAuthorized");
        }
        logger.info(TAG, "role validated");
    }
}

以下是我使用服务器的安全配置类:

@EnableWebSecurity(debug = false)
@Configuration
public class ResourceServerSecurityConfigs extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests(authz -> authz
                .antMatchers(HttpMethod.GET, "api/v1/books/**").hasAuthority("ALLOW-allowedtraffic")
                .antMatchers(HttpMethod.POST, "api/v1/books/**").hasAuthority("ALLOW-allowedtraffic")
                .antMatchers(HttpMethod.PUT, "api/v1/books/**").hasAuthority("ALLOW-allowedtraffic")
                .antMatchers(HttpMethod.DELETE, "api/v1/books/**").hasAuthority("ALLOW-allowedtraffic")
                .antMatchers(HttpMethod.GET, "api/v1/lending/**").hasAuthority("ALLOW-allowedtraffic")
                .antMatchers(HttpMethod.POST, "api/v1/lending/**").hasAuthority("ALLOW-allowedtraffic")
                .antMatchers(HttpMethod.PUT, "api/v1/lending/**").hasAuthority("ALLOW-allowedtraffic")
                .antMatchers(HttpMethod.DELETE, "api/v1/lending/**").hasAuthority("ALLOW-allowedtraffic")
                .anyRequest().authenticated())
                .oauth2ResourceServer(oauth2 -> oauth2.jwt());
    }
}

下面是堆栈跟踪:

***************************
APPLICATION FAILED TO START
***************************

Description:

Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a bean of type 'org.springframework.security.oauth2.jwt.JwtDecoder' that could not be found.


Action:

Consider defining a bean of type 'org.springframework.security.oauth2.jwt.JwtDecoder' in your configuration.

2022-09-12 10:05:57,294 ERROR [main] org.springframework.test.context.TestContextManager: Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@55787112] to prepare test instance [backend.controllers.MyAppListControllerTest@5488b5c5]
java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:43)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:248)
    at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:138)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$8(ClassBasedTestDescriptor.java:363)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:368)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$9(ClassBasedTestDescriptor.java:363)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
    at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
    at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
    at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:362)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:283)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:282)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:272)
    at java.base/java.util.Optional.orElseGet(Optional.java:369)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:271)
    at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:102)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:101)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:66)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    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:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    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)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.oauth2.jwt.JwtDecoder' available
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:132)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    ... 70 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.oauth2.jwt.JwtDecoder' available
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
    ... 91 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.oauth2.jwt.JwtDecoder' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
    at org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer$JwtConfigurer.getJwtDecoder(OAuth2ResourceServerConfigurer.java:419)
    at org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer$JwtConfigurer.getAuthenticationProvider(OAuth2ResourceServerConfigurer.java:428)
    at org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer.getAuthenticationProvider(OAuth2ResourceServerConfigurer.java:335)
    at org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer.init(OAuth2ResourceServerConfigurer.java:254)
    at org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer.init(OAuth2ResourceServerConfigurer.java:147)
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.init(AbstractConfiguredSecurityBuilder.java:338)
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:300)
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:38)
    at org.springframework.security.config.annotation.web.builders.WebSecurity.performBuild(WebSecurity.java:315)
    at org.springframework.security.config.annotation.web.builders.WebSecurity.performBuild(WebSecurity.java:90)
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:305)
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:38)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain(WebSecurityConfiguration.java:126)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    ... 92 common frames omitted
Disconnected from the target VM, address: '127.0.0.1:54592', transport: 'socket'

Process finished with exit code -1

不知道从哪里开始,我在这里没有找到任何解决的线程。请向我解释一下,将不胜感激!

编辑:我有一个常规app.properties:

logging.level.org.springframework.jdbc.core=${logLvl}
spring.datasource.url=${dbConnStr}
spring.datasource.username=${dbUser}
spring.datasource.password=${dbPw}

spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.show-sql=true
spring.jpa.hibernate.dialect=com.backend.hibernat.CustSQLServerDialect
spring.jpa.hibernate.ddl-auto = none
server.port=8081

myAppPath=${myAppPath}

tenantId=123-tenant-id-456
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://issues-uri
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://keys

还有一个正在测试/资源:

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
# spring.datasource.x
#spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
#settings
spring.h2.console.enabled=false
#app settings

共有2个答案

微生令雪
2023-03-14

如果您的测试是一个ctroller单元测试,也许您应该只使用@MockBean JwtDecoder jwtdecode

对于角色检查而不是自定义 JWT 验证程序,也许您可以配置权限转换器(从 Keycloak 角色而不是作用域),并让身份验证转换器使用此权限转换器。

这将使您能够:

  • 编写安全表达式,如@PreAuthorize(“hasAuthority('foo')”)或安全配置中的等效表达式
  • 单元测试访问控制

本文中的示例

谢善
2023-03-14

文档中编写了以下内容:

如果应用程序没有公开一个JwtDecoder bean,那么Spring Boot将公开上面的默认bean。

以下是默认JwtDecoder实现的外观:

@Bean
public JwtDecoder jwtDecoder() {
    return JwtDecoders.fromIssuerLocation(issuerUri);
}

我猜您没有在属性文件中指定< code>issuer-uri,所以Spring无法自动配置上面的bean。

在Spring Boot应用程序中,要指定要使用的授权服务器,只需执行以下操作:

 spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: https://idp.example.com/issuer

其中idp.example。com/issue是授权服务器将发布的JWT令牌的iss声明中包含的值。资源服务器将使用此属性进一步自我配置、发现授权服务器的公钥,并随后验证传入的JWT

 类似资料:
  • 我有一个应用类 我有控制器课 并且,我想为Application test编写一个测试用例,以确保创建的实例类型为HelloController 但是,我在自动连接 hello控制器变量时遇到错误(找不到 hello 控制器类型的 bean)。根据我的理解,@SpringBootTest应该创建上下文并返回一个实例。我们不需要编写任何上下文 xml 或使用任何注释Config 类来获取实例。缺少了

  • 使用spring-boot时,一切工作都很好。尽管如此,在spring-boot中已删除了注释和。我试图将代码重构为新版本,但我做不到。对于以下测试,我的应用程序在测试之前没有启动,http://localhost:8080返回404: 如何重构测试以使其在Spring-Boot1.5中工作?

  • 尝试完成Spring Boot教程:https://Spring.io/guides/gs/spring-boot/#initial 以下是我的课程: 和pom.xml: 当我尝试使用以下命令运行它时:“mvn package&&java-jar target/gs-spring-boot-0.1.0.jar”,我得到的是: “-dmaven.home=C:\program files\jetbr

  • 我的程序编译了所有内容,我没有出错,但我实际上期望tomcat应该永久在端口8080上。输出中也没有Spring。在另一个项目中,我做的一切都很好。谢谢你帮助我。 我的父母: 我的tarter.class: 我的Starter-Pom: 控制台输出: 然后什么都不会发生了。谢谢你的帮助。

  • 集成测试: 当我偶尔运行这个测试时,一切都很好,但是当我和其他测试一起运行它时,没有使用模拟的ServerThroughRabbitMQ,所以一些spring缓存强制使用旧的rabbit侦听器。 我试图调试它,我可以看到,正确的bean被autowired到测试中,但由于某些原因旧监听器使用(旧bean字段instanceID=1新mocked bean instanceID=3),测试失败(不确