10

I am developing a Spring Boot application using STS with the Gradle plugin. I have a different configuration for tests, to prevent our Selenium tests from having to login.

So in src/test/java/etc I have something like this:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public static class SecurityConfig extends WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception
    {   
        http.authorizeRequests().anyRequest().permitAll();
    }
}

Whereas in src/main/java I have an equivalent class that configures login etc, requiring login for all pages.

If I run the application through the Gradle plugin (bootRun), everything works fine.

However, if I run or debug it through Eclipse directly (e.g. right clicking on the project, Run As->Spring Boot App or by clicking the run/debug buttons in the Spring or Java view) then the test config is applied, so access is granted to all pages without login.

I'm guessing that the test classes are being included in the classpath when I start the application this way. Is there an easy way to prevent this from happening?

Martin Wilson
  • 3,386
  • 1
  • 24
  • 29
  • 3
    I could imagine you could workaround this by adding `@Profile("test")` to this class + `@ActiveProfiles("test")` on the test. That would make the bean condtional on that profile. See http://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#testcontext-ctx-management-env-profiles – zapl Nov 14 '15 at 11:28
  • Looks like a good potential solution, although even after I added @profile("test") to the test config class it is still being used when I run the app. I'll investigate this further later - thanks. – Martin Wilson Nov 14 '15 at 11:44
  • 2
    I can confirm that the problem almost certainly that runtime classpath includes 'test' things on it. It is kind of a known problem though I do not think there is an issue ticket for it. This is a problem caused by gradle's tooling model not distinuguishing between 'test' and 'runtime' classpaths. I'm afraid the easiest way to avoid this problem is to switch to using maven. I know m2e/maven does this correctly. – Kris Nov 16 '15 at 17:05
  • Thanks @Kris - I've got round it for now by removing the need for a separate config for the tests. – Martin Wilson Nov 16 '15 at 19:56
  • I have written some code in my build.gradle file that generates an Eclipse launch configuration using the runtime classpath. I use this launch configuration to run my local app server. See http://stackoverflow.com/a/40646309/1423583 – Nathan Nov 17 '16 at 03:53
  • 1
    I use maven and have the same problem. – KSobkowiak Nov 30 '16 at 16:19

3 Answers3

2

When you run the test from eclipse, the classpath is prepared by eclipse (and not by maven or gradle).

Eclipse only uses one classpath per project and does not know anything about dependency scopes (like 'compile' or 'test'). So the classpath always contains any resources of a referenced project.

You cannot change this behavior of eclipse. You need to use naming conventions, profile etc. to avoid accidental use of test resources.

1

At least Eclipse IDE Version: 2022-12 (4.26.0) has the feature that allows to exclude test code from Debug/Run configuration classpath:

Go to Run/Debug configuration you use to run your app, choose Dependencies tab, click the checkbox 'Exclude test code'.

Industrious
  • 417
  • 1
  • 3
  • 10
0

You can append @TestComponent to you test configuration class. These bean configurations will be skipped during component scan of your application. Depending on the component scan configuration, you need to define an @ComponentScan exclude filter: excludeFilters = @ComponentScan.Filter(value = TestComponent.class, type = FilterType.ANNOTATION))

StefanR
  • 538
  • 5
  • 14
  • It works, but there is one problem with this approach: you have to add spring test class in production, otherwise you will get ClassNotFoundException – Wellington Souza Nov 22 '17 at 00:40
  • @WellingtonSouza that's true. Alternatively you can also use a regexp expression to exclude test classes, e.g. `excludeFilters = @ComponentScan.Filter(pattern = ".*TestConfiguration", type = FilterType.REGEX)` – StefanR Nov 24 '17 at 08:55