Отключить защиту для модульных тестов с пружинной загрузкой
Я пытаюсь создать простой весенний загрузочный веб-проект с безопасностью. Я могу запустить приложение нормально, и безопасность работает нормально. Тем не менее, у меня есть некоторые компоненты, которые я хочу протестировать без обеспечения безопасности (или тестировать вообще - тест вообще не работает).
Я получаю исключение, указывающее, что он не может найти ObjectPostProcessor и, следовательно, не может вызвать контейнер.
Вызвано: org.springframework.beans.factory.NoSuchBeanDefinitionException: не найден квалифицирующий компонент типа [org.springframework.security.config.annotation.ObjectPostProcessor] для зависимости
14:01:50.937 [main] ОШИБКА osboot.SpringApplication - сбой запуска приложения org.springframework.beans.factory.BeanCreationException: ошибка создания бина с именем 'fmpdfApplication.ApplicationSecurity': сбой внедрения зависимостей с автопроводкой; Вложенное исключение: org.springframework.beans.factory.BeanCreationException: Не удалось автоматически связать метод: public void org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.setObjectPostProcessor(org.sject.cess.or.Secory.prision.prision.pref.Purity.Org.Secory.SecoryPr.; вложенное исключение - org.springframework.beans.factory.NoSuchBeanDefinitionException: для зависимости не найден квалифицирующий компонент типа [org.springframework.security.config.annotation.ObjectPostProcessor]: ожидается, что по крайней мере 1 компонент, который квалифицируется как кандидат на автопроводку для этой зависимости. Аннотации зависимостей: {} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues (AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.1.6.RELEraing.ra.Rease.jar.jar:..beans.factory.support.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] в org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactwebBean [spring-beans-4.1.6.RELEASE.jar: 4.1.6.RELEASE] в 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] в org.springframework.beans.factory.support.AbstractBeanFactory.doGetBe2.Bean) ~ [spring-beans-4.1.6.RELEASE.jar: 4.1.6.RELEASE] в 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] в org.springtesuwork.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) ~[spring-context-4.1.6.RELEASE.jar:4.1.6.RELEASE] в org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686) ~[spring-boot-1.2.4.RELEASE.jar:1.2.4.RELEASE] в 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. DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] в org.springframework.test.context.DefaultTestContext.xt.estContext.te -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] в org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestjjj) -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] в org.springf.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:259) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] в org.junit.internal.runners.model.Reflelelable ReflableCable.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:.6.RELEASE] at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] в org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12] в org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12] в org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12] в org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12] в org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12] в org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluatej: RunBe 61) [spring-test-4.1.6.RELEASE.jar: 4.1.6.RELEASE] по адресу org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] в 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] в org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.12.jar:4.12] по адресу com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestR78.jar: jun: j: jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj по-пору) jj ] в com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) [junit-rt.jar:na] в com.intellij.rt.execution.junit.JUnitStarter.main(JUnit 68) [junit-rt.jar:na] в sun.reflect.NativeMethodAccessorImpl.invoke0(собственный метод) ~[na:1.8.0_45] в sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62 ~ [ 1.8.0_45] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45] в java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45] в com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) [idea_rt.jar:na] Причина: org.springframework.beans.factory.BeanCreationException: Не удалось автоматически подключить метод: public void org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.setObjectPostProcessor(org.springframework.security.config.annotation.ObjectPostProcessor); вложенное исключение - org.springframework.beans.factory.NoSuchBeanDefinitionException: для зависимости не найден квалифицирующий компонент типа [org.springframework.security.config.annotation.ObjectPostProcessor]: ожидается, что по крайней мере 1 компонент, который квалифицируется как кандидат на автопроводку для этой зависимости. Аннотации зависимостей: {} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:649) ~[spring-beans-4.1.6jR..springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] в org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues (AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] ... 43 опущенных общих кадра: вызвано: org.springframework.Exanin.eans.beans.beans.beans.e Не найден квалифицируемый компонент типа [org.springframework.security.config.annotation.ObjectPostProcessor] для зависимости: ожидается, что по крайней мере 1 компонент, который квалифицируется как кандидат для автоматической передачи для этой зависимости. Аннотации зависимостей: {} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301) ~[spring-beans-4.1.6.RELEASE.jar.sraf или org: 4.1.6..beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] в org.springframework.beans.factory.acteeBault. resolDependency(DefaultListableBeanFactory.java:942) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE] в org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutowiredMetnoject.Представление_проигрывателя_пространства.Причиненный_проигрыватель_повторения_произв. (6).) ~ [spring-beans-4.1.6.RELEASE.jar: 4.1.6.RELEASE]... пропущено 45 общих кадров
Я даже не пытаюсь проверить что-либо, связанное с сетью, безопасностью или чем-то еще. Я просто тестирую один из своих компонентов. Мой юнит-тест (в Groovy) это как:
@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=false 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. Как я могу отключить пружинную безопасность для модульного тестирования не веб-вещей?
15 ответов
FmpdfApplication
вероятно аннотируется @EnableAutoConfiguration
(или с @SpringBootApplication
который мета-аннотирован с @EnableAutoConfiguration
), и это приведет к тому, что Spring Security будет выбран и настроен с помощью автоконфигурации.
Если вы хотите увидеть, что настраивается автоматически, запустите ваше веб-приложение и получите доступ к autoconfig
конечная точка (например, http://localhost:8080/autoconfig). Затем найдите "Security", чтобы увидеть, какие классы "AutoConfiguration" обнаруживаются.
Затем вы можете отключить автоматическую настройку безопасности, исключив такие классы, как это:
@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class, ManagementSecurityAutoConfiguration.class })
Конечно, вы не захотите исключать их для производственных развертываний. Таким образом, вам нужно иметь отдельный @Configuration
класс для производства и испытаний.
С Уважением,
Сэм
ps Вы также можете найти мой ответ на следующий вопрос полезным: тестирование интеграции на основе модулей Spring-Boot
ОБНОВЛЕНИЕ ОТВЕТА: Еще один вариант, который я недавно узнал, если я использую MockMvc и AutoConfigureMockMvc для тестирования своих контроллеров, я могу просто установить для него secure=false, чтобы отключить любую защиту, применимую к вашим контроллерам.
@AutoConfigureMockMvc(secure = false)
Если нет, перейдите ниже для базовой аутентификации.
Исключение, которое вы получаете, сильно отличается от того, что я получаю, но если вы хотите отключить защиту во время выполнения тестовых случаев, вы можете попробовать использовать профили и отключить базовую безопасность, используя свойства для тестового профиля. Это то, что я сделал -
- Добавлена аннотация
@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-адресам. Я надеюсь, что это работает и для вас. Удачи!!!
В моем случае, @AutoConfigureMockMvc(addFilters = false)
помог мне.
Пример:
@WebMvcTest(MyController.class)
@AutoConfigureMockMvc(addFilters = false)
@TestPropertySource(locations="classpath:application-test.properties")
public class MyControllerTests {
Ура
Попробуйте этот, чтобы отключить весеннюю загрузку безопасности для тестирования
@AutoConfigureMockMvc(secure = false)
@RunWith(SpringRunner.class)
@WebMvcTest(SampleController.class)
@AutoConfigureMockMvc(secure = false)
public class SampleControllerIntegrationTest {
Попробуйте Spring Security @WithMockUser
быстро издеваться над пользователем в тестах.
http://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/
Что касается меня, я обновил свои тестовые аннотации, чтобы исправить это. Теперь он работает нормально.
Из:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
К:
@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
@ActiveProfiles(value = "test")
@AutoConfigureMockMvc(addFilters = false)
Если ваше приложение не было веб-базой, но вам нужен Jar-файл Spring-Security как зависимость, и вы не хотите, чтобы во время тестирования авто-конфигурации Spring-boot для Spring-Security, вы можете добавить
@SpringBootTest(webEnvironment = WebEnvironment.NONE)
в вашем тестовом классе.
Вы можете просто добавить эту аннотацию в свой тестовый класс:@AutoConfigureMockMvc(addFilters = false)
У меня ничего не получалось, пока я наконец не нашел это решение:
@Bean
@Profile("integration-test")
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring()
.antMatchers("/**");
}
И для тестов используйте профиль «интеграционный-тест».
Это решение, которое я использую в весенней загрузке 2.7.x
Этот подход использует механизм профиля.
При использовании тестового профиля отключается защита для всех вызовов.
@Bean
@Profile("test")
public WebSecurityCustomizer webSecurityCustomizer() {
//Since we added the Spring Security to pom.xml and the spring security default
//Behavior is ... well to secure and block all traffic
//This will disable the behavior when testing none secured related tests
return web -> web.ignoring().anyRequest();
}
Если вы хотите решить проблему с помощью application.yml, вы можете сделать следующее (решение такое же, как принятый ответ Сэма Браннена, но с файлом свойств). Если еще нет, создайте application.yml в папке test.
spring:
profiles:
active: integration-test
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
- org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
Затем вы должны установить свой тест интеграции на:
@SpringBootTest(webEnvironment = RANDOM_PORT)
@ActiveProfiles("integration-test")
Хотя я понимаю, что вы хотите отключить безопасность, есть одна аннотация от Mockito, позволяющая вам издеваться над пользователем
@WithMockUser(username = "Test", authorities = {"USER"})
Вы можете использовать его с классом для имитации всех методов, а также с методами. Метод переопределит класс.
Делая это, вы можете протестировать методы, специфичные для администратора. Я нахожу это полезным.
В тестах контроллера вы можете быть вынуждены имитировать userService, а также кодировщик паролей, как показано ниже.
@ExtendWith(SpringExtension.class)
@WebMvcTest(Controller.class)
@WithMockUser(username = "Test", authorities = {"USER"})
class ControllerTest {
@Autowired
MockMvc mockMvc;
@MockBean
AppUserService userService;
@MockBean
PasswordEncoder passwordEncoder;
@MockBean
SomeBusinessService someBusinessService;
Другим способом может быть использование @ActiveProfile
, Создайте отдельный файл yml, например application-nosecurity.yml
, с содержанием ниже:
security:
ignored: /**
Теперь аннотируйте тестовый класс с помощью @ActiveProfile("nosecurity")
в котором вы не хотите использовать безопасность, как показано ниже:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@ActiveProfile("nosecurity")
public class BlaBlaTest {
## Your Test Code
}
Если у вас есть эта ошибка только на webMvcTest, вы должны исключить конфигурацию класса безопасности для этих тестов:
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Profile(value = {"!test"})
public class XXXX extends WebSecurityConfigurerAdapter {
Для меня исправлением было обновить мои тестовые аннотации. Я заменил:
@SpringApplicationConfiguration(classes = { MyApplication.class })
@RunWith(SpringJUnit4ClassRunner.class)
с
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = MyApplication.class)