2015-07-01 98 views
17

我试图创建一个简单的弹簧启动web项目与安全性。我可以启动应用程序,安全性正常。然而,我有一些组件,我想测试没有安全性(或测试 - 我无法得到测试工作)。使用弹簧启动禁用单元测试的安全性

我收到一个异常,指出它找不到ObjectPostProcessor,因此无法调出容器。

造成的:org.springframework.beans.factory.NoSuchBeanDefinitionException:[org.springframework.security.config.annotation.ObjectPostProcessor]找不到类型的排位豆的依赖

 
14:01:50.937 [main] ERROR o.s.boot.SpringApplication - Application startup failed 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fmpdfApplication.ApplicationSecurity': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.setObjectPostProcessor(org.springframework.security.config.annotation.ObjectPostProcessor); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.config.annotation.ObjectPostProcessor] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757) ~[spring-context-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) ~[spring-context-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686) ~[spring-boot-1.2.4.RELEASE.jar:1.2.4.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) ~[spring-boot-1.2.4.RELEASE.jar:1.2.4.RELEASE] 
    at org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:103) [spring-boot-1.2.4.RELEASE.jar:1.2.4.RELEASE] 
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:212) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:200) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:259) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12] 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:261) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:219) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12] 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12] 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12] 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12] 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12] 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12] 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.12.jar:4.12] 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78) [junit-rt.jar:na] 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) [junit-rt.jar:na] 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) [junit-rt.jar:na] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45] 
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45] 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) [idea_rt.jar:na] 
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.setObjectPostProcessor(org.springframework.security.config.annotation.ObjectPostProcessor); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.config.annotation.ObjectPostProcessor] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:649) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    ... 43 common frames omitted 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.config.annotation.ObjectPostProcessor] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:606) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    ... 45 common frames omitted 

我甚至试图测试任何与网络或安全相关的任何事情。我只是单元测试我的一个组件。 我的单元测试(在常规)是这样的:

@RunWith(SpringJUnit4ClassRunner) 
@SpringApplicationConfiguration(classes = FmpdfApplication) 
@ActiveProfiles(["test", "mockstore"]) 
class PdfUpdaterTest { 

    @Resource PdfUpdater pdfUpdater 
    ... 

我的(相关)gradle这个依赖关系是:

compile("org.springframework.boot:spring-boot-starter-actuator") 
compile("org.springframework.boot:spring-boot-starter-security") 
compile("org.springframework.boot:spring-boot-starter-web") 
compile("org.springframework.boot:spring-boot-starter-jdbc") 
testCompile("org.springframework.boot:spring-boot-starter-test") 

我已经尝试设置 management.security.enabled =假 security.basic .enabled = false 但这没有帮助

其他一些相关信息:我需要定制安全性,所以我遵循以下模式:

@Configuration 
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 
protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter { 
     @Override 
     public void configure(AuthenticationManagerBuilder auth) throws Exception { 
    .. 

这是问题的一部分吗?如果有关联,有没有办法让这个@Lazy?

更新:如果我将单元测试标记为@WebIntegrationTest,那么一切正常 - 但它启动了一个嵌入式tomcat服务器。如何禁用单元测试非web事物的spring安全性?

+0

是FmpdfApplication模拟/测试或实际应用类? – ikumen

回答

15

FmpdfApplication很可能与注释@EnableAutoConfiguration(或@SpringBootApplication这是元标注有@EnableAutoConfiguration),这将导致春季安全被拾起,并通过自动配置进行配置。

如果要查看自动配置的内容,请启动您的Web应用程序并访问autoconfig端点(例如,http://localhost:8080/autoconfig)。然后搜索“安全”以查看哪些“AutoConfiguration”类正在被检测到。

然后,您可以通过排除这样的类禁用安全的自动配置:

@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class, ManagementSecurityAutoConfiguration.class }) 

当然,你不会要排除他们的生产部署。因此,您需要有一个单独的@Configuration类用于生产和测试。

问候,

山姆

附:你也可以找到我对以下问题的回答很有用:Spring-Boot module based integration testing

+0

只需注意@EnableAutoConfiguration(exclude = {SecurityAutoconfiguration.class,ManagementWebSecurityAutoConfiguration.class})将位于src/test/java中的@SpringBootApplication注释类中。还要注意使用ManagementWebSecurityAutoConfiguration.class(我使用的是spring boot 1.3.0) –

20

你唯一的例外是比我已经非常不同,但如果你想在运行测试用例来禁用安全性,您可以使用配置文件和禁止使用属性测试配置文件的基本安全性尝试。这是我做过什么 -

  1. 添加注释@Profile(value = {"development", "production"})我实施WebSecurityConfigurerAdapter -

    @Configuration 
    @EnableWebSecurity 
    @Profile(value = {"development", "production"}) 
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 
    
  2. 现在,在test/resources,创建application-test.yml定义测试配置文件属性和添加此 -

    # Security enable/disable 
    security: 
        basic: 
        enabled: false 
    
  3. 现在,在您的测试案例中,添加此注释以应用活动配置文件@ActiveProfiles(value = "test")。这是我的课是什么样子 -

    @RunWith(SpringJUnit4ClassRunner.class) 
    @SpringApplicationConfiguration(classes = Application.class) 
    @WebAppConfiguration 
    @ActiveProfiles(value = "test") 
    @IntegrationTest({"server.port=0"}) 
    public class SampleControllerIntegrationTest { 
    

这样做禁用安全为我的测试情况下,我能够访问验证URL。我希望这也适合你。祝你好运!

+0

我也喜欢这个解决方案,谢谢! –

+0

有史以来最好的解决方案 –

+0

接受的答案并不适用于我,我使用OAuth2并在资源服务器上执行此操作,因此将@Profile注释添加到ResourceServerConfigurerAdapter,但其余部分相同,并且工作正常。 – 3urdoch

0

如果您的应用程序是不是网络的基础,但你需要弹簧安全罐子的依赖,你不想为弹簧安全弹簧启动的自动配置测试时, 您可以添加

@SpringBootTest(webEnvironment = WebEnvironment.NONE)

在你的测试类。

0

对我来说,解决的办法是更新我的测试注释。我换成:

@SpringApplicationConfiguration(classes = { MyApplication.class }) 
@RunWith(SpringJUnit4ClassRunner.class) 

@RunWith(SpringRunner.class) 
@SpringBootTest 
@ContextConfiguration(classes = MyApplication.class)