Brad Solomon
Brad Solomon

Reputation: 40918

Integration-testing a Spring Boot @Service without SpringBootApplication

I have a standalone Spring Boot @Service in its own repository. The repository is a "helper library" and does not itself contain a @SpringBootApplication or any @RestController. The Service uses an Autowired S3Template from Spring Cloud AWS.

How can I write integration tests of the @Service without using @SpringBootApplication or having a main class?

I've seen several related answers involving @TestConfiguration and other annotations, but am struggling to put the pieces together and get this working with Spring Boot 3.3.x.

I have produced a minimal, reproducible example (Spring Boot 3.3, JDK 21) at:

https://github.com/solomonbrjnih/so-service-no-application

As-is, this will run cleanly with passing tests using mvn clean test -- however, only because I have added a @SpringBootApplication in src/test. This does not seem like the idiomatic way, and this approach will break if I attempt to use Maven Failsafe Plugin to run integration tests "the right way".

To be clear, I do not want to do any mocking here--I want to test the real service as-is, in this case against an actual Amazon S3 (development) environment.

What I have tried:

I've tried using @TestConfiguration, but am getting errors related to autowiring/beans:

// TestConfig.java
package foo.demo;

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;

@TestConfiguration
public class TestConfig {

    @Bean
    public DemoService service() {
        return new DemoService();
    }
}
// DemoApplicationTests.java
...
@ExtendWith(SpringExtension.class)
@Import(TestConfig.class)
class DemoApplicationTests {

    @Autowired
    private DemoService service;
...

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'service': Unsatisfied dependency expressed through field 's3Template': No qualifying bean of type 'io.awspring.cloud.s3.S3Template' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Upvotes: 1

Views: 44

Answers (1)

Roar S.
Roar S.

Reputation: 11134

Spring Boot docs contains a guide for Creating a Multi Module Project. Section "Testing the Service Component" contains

@SpringBootTest("service.message=Hello")
public class MyServiceTest {

  @Autowired
  private MyService myService;

  @Test
  public void contextLoads() {
    assertThat(myService.message()).isNotNull();
  }

  @SpringBootApplication // this is the one you need
  static class TestConfiguration {
  }
}

An alternative is to add this to a separate class TestConfiguration

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestConfiguration {
}

If any configuration is required, put this in an application.yml or application.properties in test/resources.

Upvotes: 1

Related Questions