Я создал приложение, использующее MongoDB, и столкнулся с проблемой тестирования.
Пока я использовал JPA и некоторую реляционную базу данных, я использовал некоторый тестовый уровень, который переключал постоянство на базу данных в памяти (linke HSQLDB или MySQL) для целей тестирования. Таким образом я смог ограничить операции ввода-вывода и ускорить тесты. Однако с MongoDB и Spring Data очень удобно использовать репозитории на основе интерфейсов, расширяющих MongoRepository.
Мой вопрос: как бороться с модульным тестированием и функциональным тестированием при использовании репозиториев? Например, у меня есть простой класс, который помечен как документ монго:
public class Company {
@Id
private String id;
@NotEmpty
private String name;
private String description;
private String website;
private String logo;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getLogo() {
return logo;
}
public void setLogo(String logo) {
this.logo = logo;
}
}
и соответствующий репозиторий:
@Repository
public interface CompanyRepository extends MongoRepository<Company, Serializable> {
}
Он используется в соответствующем контроллере:
@RestController
public class CompanyController {
private static final Logger log = LoggerFactory.getLogger(CompanyController.class);
@Autowired
private CompanyRepository repository;
@RequestMapping(value = "/company", method = RequestMethod.POST)
public void create(@Valid @RequestBody(required = true) Company company) {
repository.save(company);
}
}
Наконец, я сделал два теста (однако это может быть один, охватывающий обе задачи), которые охватывают API-интерфейс контроллера и формат данных (где я имитирую репозиторий, чтобы предотвратить операции ввода-вывода, и он работает хорошо), и второй, где я хочу убедиться, что переданный объект был успешно сохранен. Как оказалось не все так просто. Прежде всего (поправьте меня, если я ошибаюсь) нет реализации монго в памяти. Во-вторых, я не могу проверить с помощью mockito выполнение метода сохранения из-за наследования, я полагаю.
@ContextConfiguration(classes = Application.class)
@WebAppConfiguration
public class CompanyControllerNGTest extends AbstractTestNGSpringContextTests {
@Mock
private CompanyRepository repositoryMock;
@Autowired
@InjectMocks
private CompanyController controller;
private MockMvc mockMvc;
@BeforeMethod
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@DataProvider
public static Object[][] companyJsonProvider() {
return new Object[][]{
{Json.createObjectBuilder()
.add("name", "JakasFirma")
.add("description", "jakas firma opis")
.add("website", "www.jakasfirma.com")
.add("logo", "jakies logo")
.build(), status().isOk()},
{Json.createObjectBuilder()
.add("name", "JakasFirma")
.build(), status().isOk()},
{Json.createObjectBuilder()
.add("description", "jakas firma opis")
.add("website", "www.jakasfirma.com")
.add("logo", "jakies logo")
.build(), status().isBadRequest()},
{Json.createObjectBuilder()
.build(), status().isBadRequest()},
};
}
@Test(dataProvider = "companyJsonProvider", enabled = false)
public void apiTest(JsonObject companyJson, ResultMatcher expectedStatus) throws Exception {
//given
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
String content = companyJson.toString();
//when
mockMvc.perform(post("/company").contentType(MediaType.APPLICATION_JSON).content(content)).
//then
andExpect(expectedStatus);
}
@Test
public void shouldCreate() throws Exception {
//given
//when
controller.create(mock(Company.class));
//then
//verify(repositoryMock, times(1)).save(any(Iterable.class));
}
}
Я подумал о том, чтобы ввести слой dao между контроллером и репозиторием, который можно было бы смоделировать и проверить ботом, это добавляет сложности и силы для инкапсуляции каждого метода, используемого репозиторием. Также это не устраняет проблему, а частично перемещает ее на более низкий уровень. Есть ли какой-либо метод или практика, которые могли бы помочь справиться с такой проблемой? Или, может быть, мне следует использовать другой подход с монго?