Spring boot: внедрение бинов из тестов в веб-среду - PullRequest
0 голосов
/ 26 января 2020

Я создаю несколько интеграционных тестов для своего примера приложения и мне было интересно, смогу ли я создать некоторые тестовые данные в своих тестах, а затем внедрить их на работающий сервер. Я предпочитаю не проверять мои данные, потому что я хочу, чтобы мой тест проходил через весь стек.

Я понимаю, что в документации Spring Boot говорится, что сервер и тесты выполняются в 2 отдельных потоках, но возможно ли это пропустить тот же контекст через?

Код, который у меня есть:

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ArtistResourceTests {
    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private ArtistRepository artistRepository;

    @Test
    @Transactional
    public void listReturnsArtists() {
        Artist artist = new DataFactory().getArtist();
        this.artistRepository.save(artist);

        ParameterizedTypeReference<List<Artist>> artistTypeDefinition = new ParameterizedTypeReference<List<Artist>>() {};
        ResponseEntity<List<Artist>> response = this.restTemplate.exchange("/artists", HttpMethod.GET, null, artistTypeDefinition);

        assertEquals(1, response.getBody().size());
    }
}

Но это возвращает 0 результатов вместо 1 результата.

Ответы [ 2 ]

1 голос
/ 26 января 2020

Я думаю, что вы не взаимодействуете с каким-либо удаленно работающим сервером.

SpringBootTest Аннотация запускает весь микросервис локально внутри теста. В противном случае, если ваш тест представляет собой просто серию вызовов к удаленному серверу, вам не нужно @SpringBootTest (и вообще не нужна весенняя загрузка :)).

Таким образом, у вас есть контекст приложения прямо внутри теста. Теперь вы спрашиваете, как предварительно заполнить данные. Это слишком широко, так как вы не указываете, где именно хранятся данные и какие слои сохраняемости данных задействованы (RDBMS, Elasticsearch, Mon go, ...)?

Одна возможная универсальная цель используется слушатель выполнения теста , который может иметь метод beforeTestMethod.

Контекст приложения запускается, так что вы действительно можете подготовить данные пользовательским способом и сохранить их в базе данных ваш выбор (через ввод DAO в слушатель или что-то в этом роде).

Еще один интересный способ использования Flyway - обеспечить миграцию в папке src/test/resources/data, чтобы flyway автоматически выполнял миграции во время теста.

Обновление

В комментарии говорится, что в этом случае используется база данных H2, при условии, что источник данных настроен правильно и действительно обеспечивает соединения с H2, самый простой способ - запустить SQL скрипты со вставками данных:

@Sql(scripts = {"/scripts/populateData1.sql", ..., "/scripts/populate_data_N.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
public void myTest() {
...
}

Теперь, если вам нужно работать с

this.artistRepository.save(artist);

, тогда Spring не заботится о потоках. Он может вводить любые данные, если «данные» являются компонентом (или ресурсом), поскольку вы работаете с объектами (Artist), это должен быть компонент.

Создайте TestConfiguration с помощью bean Artist, убедитесь, что он находится в том же пакете, что и test (чтобы процесс сканирования при весенней загрузке загрузил конфигурацию), и введите его в тест с @Autowired как обычно:

@TestConfiguration
public class ArtistsConfiguration {

   @Bean 
   public Artist artistForTests() {
       return new Artist(...);
   }
}


@Import(ArtistsConfiguration.class)
@SpringBootTest
public class MyTest {

   @Autowired
   private Artist artist;

   ....
}
0 голосов
/ 26 января 2020

Вы можете использовать @ContextConfiguration, например, так:

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
@ContextConfiguration(locations = {"/testApplicationContext.xml"})
public class TestGetPerson {

    @Autowired
    private PersonService personService;
...

Затем в testApplicationContext вы указываете пакеты, которые Spring должен сканировать:

<context:component-scan base-package="nl.example.server.service"/>
<context:component-scan base-package="nl.example.server.test.db"/>

Может быть аннотация, которая достигает того же самого предмет. Я делаю так, чтобы Spring сканировал большинство пакетов так же, как и в реальном приложении, за исключением компонентов базы данных: я использую базу данных памяти H2 для тестирования. Аннотация Profiles сообщает Spring, какие классы следует использовать в тесте. Кроме того, вы можете настроить (используя @Configuration в отсканированном пакете) определенные классы для Mockito mocks:

@Configuration
@Profile("test")
public class CustomerManagerConfig {
@Bean("customerManager")

    public CustomerManager customerManager() {
        return Mockito.mock(CustomerManager.class);
    }
}

Это не запускает ваши тестовые данные на отдельном сервере, но запускает тест в среда, которая напоминает среду вашего приложения так близко, как вам нравится.

Что касается вашего вопроса, вместо использования макета Mockito, вы можете создать свой собственный макет, который внедрит ваши тестовые данные в любой из компонентов, которые вам нравятся.

...