Home > Enterprise >  Defining tomcat property in a test running with @SpringBootTest
Defining tomcat property in a test running with @SpringBootTest

Time:10-05

My application uses spring-boot 2.5.5.

I set a property for Tomcat at application startup to allow encoded slash in @PathVariable :

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
        SpringApplication.run(App.class, args);
    }

}

Everything works fine when I start the app, except in my integration tests :

@ActiveProfiles("test-connected")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ExtendWith(SpringExtension.class)
class GlobalFullTest {

When I debug the org.apache.tomcat.util.buf.UDecoder class : I see that the property org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH is null when class is loaded, so a default value false is set.

I tried the following :

  • Adding System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true"); in the @BeforeAll method of my test
  • Adding properties = { "org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true" } in the @SpringBootTest annotation.
  • Adding org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: true in my application-test-connected.yaml
  • Using WebServerFactoryCustomizer :
@Configuration
public class WebServerConfiguration {

    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> customizer() {
        return factory -> factory.addConnectorCustomizers(connector -> connector.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true"));
    }

}

But none of these worked : when the property is retrieved by org.apache.tomcat.util.buf.UDecoder class, its value is always null.

How could I set the property before the org.apache.tomcat.util.buf.UDecoder class is loaded ?

CodePudding user response:

Referring to How to set environment variable or system property in spring tests?

The simplest way

Follow add static initializer in the class

...
class GlobalFullTest {
    static {
        System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
    }
...
}
down side is we need to copy that for every test.

Clean way

create ApplicationContextInitializer, which can be reused in the Spring application and any other test.

public class CustomApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
{
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext)
    {
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
    }
}

...
@ContextConfiguration(initializers = CustomApplicationContextInitializer.class,...)
class GlobalFullTest {
...

  • Related