Вопрос или проблема
Проблема в 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
, которая запускает только определённые компоненты. Давайте попробуем решить проблему шаг за шагом.
Решение проблемы
-
Создание общего тестового класса:
Рассмотрите возможность создания общего базового класса для тестов, который будет загружать вашу конфигурацию MongoDB.
-
Использование
@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"))); // Замените на ожидаемое поле
}
}
Объяснение изменений:
-
SpringBootTest: Замена
@WebMvcTest
на@SpringBootTest
позволяет загружать все бины, включая MongoDB. Это решает вашу проблему с отсутствием необходимого бинаRepositories
. - AutoConfigureMockMvc: Добавление этой аннотации позволяет Spring автоматически сконфигурировать
MockMvc
, что требуется для выполнения запросов.
Заключение
Проблема возникла из-за того, что @WebMvcTest
не загружает все необходимые бины и компоненты. Используя @SpringBootTest
, вы сможете загрузить все необходимые зависимости, включая MongoDB, что решит вашу проблему. Если вам нужно тестировать только контроллеры, вы можете оставить существующий тест, но убедитесь, что ваши репозитории правильно настроены и загружаются в тестовом контексте.