Проблема в Mongo Репозиториях с тестами spring boot junit5 и testcontainers

Вопрос или проблема

Проблема в Mongo Репозиториях с тестами spring boot junit5 и testcontainers

Столкнулись с проблемой репозиториев в приведенной ниже тестовой конфигурации.


import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.junit.jupiter.api.AfterAll;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory;
import org.springframework.data.mongodb.gridfs.GridFsOperations;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.containers.wait.strategy.Wait;

    @SpringBootTest
    @TestConfiguration
    public class MongoTestConfig {
        static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.4.2")
                .withExposedPorts(27017)
            .waitingFor(Wait.forListeningPort());

    static {
        mongoDBContainer.start();
    }

    // Метод для получения URL подключения к MongoDB с указанным именем базы данных
    private String getMongoUrl(String dbName) {
        return String.format("mongodb://%s:%d/%s",
                mongoDBContainer.getContainerIpAddress(),
                mongoDBContainer.getMappedPort(27017),
                dbName);
    }

    @Bean
    @Primary
    public MongoTemplate mongoTemplate() {
        String databaseName = "test"; // Замените на необходимое имя базы данных
        String mongoUrl = getMongoUrl(databaseName);
        System.out.println("Подключение к MongoDB по адресу: " + mongoUrl); // Логирование URL подключения
        return new MongoTemplate(new SimpleMongoClientDbFactory(mongoUrl));
    }

    @Bean
    @Primary
    public MongoClient mongoClient() {
        String mongoUrl = getMongoUrl("test"); // То же имя базы данных
        System.out.println("Создание MongoClient для: " + mongoUrl);
        return MongoClients.create(mongoUrl);
    }

    @Bean
    public GridFsOperations gridFsOperations(MongoTemplate mongoTemplate) {
        return new GridFsTemplate(mongoTemplate.getMongoDbFactory(), mongoTemplate.getConverter());
    }

    @AfterAll
    static void stopContainer() {
        mongoDBContainer.stop();
    }
}

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.hamcrest.Matchers.*;

import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;

@WebMvcTest(AccountQueryController.class) // Замените на ваш фактический класс контроллера
public class AccountQueryControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @InjectMocks
    AccountQueryController accountQueryController;

    @Test
    public void searchByOrgAndGroupAndName_ShouldReturnAccounts() throws Exception {
        String query = "testQuery";

        mockMvc.perform(get("/byorgandgroupandname")
                        .param("query", query))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$", hasSize(greaterThan(0)))) // Предполагается, что возвращается список
                .andExpect(jsonPath("$[0].name", is("SampleName"))); // Замените на ожидаемое поле
    }
}

Получаем следующую ошибку:

Вызвано: org.springframework.beans.factory.NoSuchBeanDefinitionException: Не найдено подходящего бина типа ‘org.springframework.data.repository.support.Repositories’: ожидался как минимум 1 бин, подходящий для автоматической подстановки. Аннотации зависимости: {}

Ответ или решение

Ваша проблема заключается в том, что тесты не могут найти необходимые бины, которые должны быть созданы с помощью Spring Data MongoDB, таких как Repositories. Это может быть связано с тем, что ваш тестовый контекст для контроллера AccountQueryController не видит вашу конфигурацию MongoDB или репозитории, потому что вы используете аннотацию @WebMvcTest, которая запускает только определённые компоненты. Давайте попробуем решить проблему шаг за шагом.

Решение проблемы

  1. Создание общего тестового класса:

    Рассмотрите возможность создания общего базового класса для тестов, который будет загружать вашу конфигурацию MongoDB.

  2. Использование @SpringBootTest вместо @WebMvcTest:

    Если вам нужно тестировать компоненты, которые зависят от MongoDB, вам может потребоваться использовать @SpringBootTest, который загружает весь контекст приложения, включая конфигурацию MongoDB.

Вот как можно изменить ваш тест:

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.hamcrest.Matchers.*;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
@AutoConfigureMockMvc // Позволяет использовать MockMvc
public class AccountQueryControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void searchByOrgAndGroupAndName_ShouldReturnAccounts() throws Exception {
        String query = "testQuery";

        mockMvc.perform(get("/byorgandgroupandname")
                        .param("query", query))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$", hasSize(greaterThan(0))))
                .andExpect(jsonPath("$[0].name", is("SampleName"))); // Замените на ожидаемое поле
    }
}

Объяснение изменений:

  1. SpringBootTest: Замена @WebMvcTest на @SpringBootTest позволяет загружать все бины, включая MongoDB. Это решает вашу проблему с отсутствием необходимого бина Repositories.

  2. AutoConfigureMockMvc: Добавление этой аннотации позволяет Spring автоматически сконфигурировать MockMvc, что требуется для выполнения запросов.

Заключение

Проблема возникла из-за того, что @WebMvcTest не загружает все необходимые бины и компоненты. Используя @SpringBootTest, вы сможете загрузить все необходимые зависимости, включая MongoDB, что решит вашу проблему. Если вам нужно тестировать только контроллеры, вы можете оставить существующий тест, но убедитесь, что ваши репозитории правильно настроены и загружаются в тестовом контексте.

Оцените материал
Добавить комментарий

Капча загружается...