2

I'm facing a problem where one of my integration tests affects the other. For example this delete test:

class DeleteCustomerIntegrationTest extends AbstractConfigurationTest {

   @Test
   void deleteCustomer_shouldReturnStatusNoContent() throws Exception {
   mockMvc.perform(delete("/api/v1/customer/1")).andExpect(status().isNoContent());
   }

Will affect this get list of customer test:

  @Test
  void listCustomers_shouldMatchExpectedResponseObject() throws Exception {
    String expectedJson = """ [object goes here] """;


    mockMvc.perform(get("/api/v1/customers").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
        .andExpect(content().json(expectedJson));
  }

My test configuration class is:

@AutoConfigureMockMvc
@SpringBootTest
public class AbstractConfigurationTest {

  @Autowired
  protected MockMvc mockMvc;

  private static final PostgreSQLContainer<?> POSTGRESQL_CONTAINER;
  private static final Logger LOGGER = LoggerFactory.getLogger(AbstractConfigurationTest.class);

  static {
    POSTGRESQL_CONTAINER =
        new PostgreSQLContainer<>("postgres:15-alpine").withDatabaseName("customers").withUsername("customers").withPassword("customers")
            .withCopyFileToContainer(MountableFile.forClasspathResource("01_init.sql"), "/docker-entrypoint-initdb.d/01_init.sql")
            .withCopyFileToContainer(MountableFile.forClasspathResource("02_data.sql"), "/docker-entrypoint-initdb.d/02_data.sql")
            .withLogConsumer(new Slf4jLogConsumer(LOGGER));

    POSTGRESQL_CONTAINER.start();
  }

  @DynamicPropertySource
  static void dynamicProperties(DynamicPropertyRegistry registry) {
    registry.add("spring.datasource.url", POSTGRESQL_CONTAINER::getJdbcUrl);
    registry.add("spring.datasource.username", POSTGRESQL_CONTAINER::getUsername);
    registry.add("spring.datasource.password", POSTGRESQL_CONTAINER::getPassword);
    registry.add("spring.datasource.driver-class-name", POSTGRESQL_CONTAINER::getDriverClassName);
  }
}

And then in my test classes I just extend this class as shown above. But i haven't found any solution to isolate the tests in an efficient way.

What i've tried is:

  1. use @DirtiesContext on class level, which will reset the application context before every test class, which can get expensive
  2. use the @Transactional annotation that spring provides for reverting back the state of the data, but it doesn't seem to work with Testcontainers.

I haven't found any mention of this in the documentation either. How are you solving this problem in your projects?

1

1 Answer 1

0

You can define a constructor

public AbstractConfigurationTest{
    //copy whatever you need
    //- multiple times for performance
    //- cloned for integrity
    //into data members
}

So you can execute mockMvc.perform(get("/api/v1/customers").contentType(MediaType.APPLICATION_JSON)) and possibly clone it if something may override its content. Store it into a data member and then later in the test you can do

mystuff.
    .andExpect(status().isOk())
    .andExpect(content().json(expectedJson))

Make sure you properly defined and initialized mystuff.

Sign up to request clarification or add additional context in comments.

1 Comment

Sounds more like a workaround. I was looking for a conventional approach to solve this in a good way. But i guess there isn't one except having one container per test class or making your tests never overlap (if possible) or use @DirtiesContext to destroy the spring context between tests

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.