Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce additional @Nested tests in test suite #23929

Open
sbrannen opened this issue Oct 28, 2020 · 5 comments
Open

Introduce additional @Nested tests in test suite #23929

sbrannen opened this issue Oct 28, 2020 · 5 comments
Labels
type: task A general task

Comments

@sbrannen
Copy link
Member

Since #12470 has been resolved and due to the general support for automatically inheriting test configuration from enclosing classes for JUnit Jupiter @Nested tests in Spring Framework 5.3, it would be good to have more @Nested tests in the Spring Boot test suite in order to verify the expected behavior for various Spring Boot Test annotations when using @Nested test classes.

Aside from tests that verify the default, inherited behavior, it would also be good to have a few dedicated tests that verify support for @NestedTestConfiguration(OVERRIDE) semantics for Spring Boot Test annotations.

For Spring Framework, I added several such test classes in the org.springframework.test.context.junit.jupiter.nested package which may serve as inspiration.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Oct 28, 2020
@philwebb philwebb added type: task A general task and removed status: waiting-for-triage An issue we've not yet triaged labels Oct 29, 2020
@philwebb philwebb added this to the General Backlog milestone Oct 29, 2020
@fbiville
Copy link

I initially opened an issue about nested test support against Spring Data Commons. This was the wrong place since this is not a Spring Data issue but rather possibly a Spring Boot or Framework one.

I could not make nested tests work with Spring Data JPA 2.4.1 (Spring Boot 2.4.0). I also tried with the latest Spring Data Neo4j (in a private repository) with the same result.

You can find the sample JPA repository here with reproduction instructions: https://github.com/fbiville/spring-data-jpa-nested.

@wilkinsona
Copy link
Member

Thanks, @fbiville. I think this is a Spring Framework bug. As far as I can tell the @DynamicPropertySource isn't being picked up by ActorTests and MovieTests. As a result, the spring.datasource.url property isn't set so the DataSource can't be created.

@wilkinsona
Copy link
Member

wilkinsona commented Nov 13, 2020

The tests pass and share a single context if the use of @DynamicPropertySource is replaced with an equivalent ApplicationContextIntializer:

package com.example.demo;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace.NONE;
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.NestedTestConfiguration;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import com.example.demo.DemoApplicationTests.PropertiesInitializer;
import com.example.demo.actors.Actor;
import com.example.demo.actors.ActorRepository;
import com.example.demo.movies.Movie;
import com.example.demo.movies.MovieRepository;

@Testcontainers
@DataJpaTest
@AutoConfigureTestDatabase(replace = NONE)
@NestedTestConfiguration(INHERIT)
@ContextConfiguration(initializers = PropertiesInitializer.class)
class DemoApplicationTests {

    @Autowired
    EntityManager entityManager;

    @Container
    private static final MySQLContainer<?> mysqlContainer = new MySQLContainer<>("mysql:5.7");

    @Nested
    class ActorTests {

        @Autowired
        ActorRepository actorRepository;

        @BeforeEach
        void prepareActors() {
            Query query = entityManager.createQuery("DELETE FROM Actor");
            query.executeUpdate();
            entityManager.persist(actor("Emil Eifrem"));
        }

        @Test
        void loads_actors() {
            List<Actor> actors = actorRepository.findAll();

            assertThat(actors).hasSize(1);
            assertThat(actors.iterator().next().getName()).isEqualTo("Emil Eifrem");
        }

        private Actor actor(String name) {
            Actor actor = new Actor();
            actor.setName(name);
            return actor;
        }
    }

    @Nested
    class MovieTests {

        @Autowired
        MovieRepository movieRepository;

        @BeforeEach
        void prepareMovies() {
            Query query = entityManager.createQuery("DELETE FROM Movie");
            query.executeUpdate();
            entityManager.persist(movie("The Matrix"));
        }

        @Test
        void loads_movies() {
            List<Movie> movies = movieRepository.findAll();

            assertThat(movies).hasSize(1);
            assertThat(movies.iterator().next().getTitle()).isEqualTo("The Matrix");
        }

        private Movie movie(String title) {
            Movie movie = new Movie();
            movie.setTitle(title);
            return movie;
        }
    }
    
    static class PropertiesInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    
        @Override
        public void initialize(ConfigurableApplicationContext applicationContext) {
            TestPropertyValues.of("spring.datasource.url=" + mysqlContainer.getJdbcUrl(),
                    "spring.datasource.username=" + mysqlContainer.getUsername(),
                    "spring.datasource.password=" + mysqlContainer.getPassword(), 
                    "spring.jpa.hibernate.ddl-auto=create").applyTo(applicationContext);;
        }
        
    }

}

@wilkinsona
Copy link
Member

@fbiville Can you please open a Spring Framework issue and comment here with a link to it so that @sbrannen can take a look?

@fbiville
Copy link

fbiville commented Nov 13, 2020

Issue created: spring-projects/spring-framework#26091.
Sorry for reporting that issue against the wrong project twice 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: task A general task
Projects
None yet
Development

No branches or pull requests

5 participants