Micronaut-Data JDBC - несколько диалектов для тестирования и производства - PullRequest
0 голосов
/ 01 декабря 2019

Документы Mirconaut по JDBC-репозиториям ясно говорят нам, что нам нужно создать тестовый репозиторий для тестирования на другом диалекте. Я думаю, что это будет управляемым (например, Postgres для производства и H2 для тестирования).

Проблема в том, что я должен повторить свои методы (например, find ()) в тестовом хранилище. У меня есть хранилище книг и тестовое хранилище:

@JdbcRepository(dialect = Dialect.POSTGRES)
interface BookRepository extends CrudRepository<Book, Long> {
  Optional<Book> find(String title);
}

@JdbcRepository(dialect = Dialect.H2)
@Replaces(bean = BookRepository)
@Requires(env = ["test"])
interface TestBookRepository extends BookRepository {
  // Optional<Book> find(String title);
  // Required to make the find() method appear in the TestBookRepository
}

Чтобы сделать метод find () доступным в TestBookRepository, мне пришлось повторить этот метод (см. Строку с комментариями выше).

Есть ли лучший способ избежать повторения? Методы интерфейса CrudRepository доступны в TestBookRepository без проблем. Почему метод find () не обрабатывается одинаково?

Кстати, я не хочу издеваться над тестовым хранилищем. Я хочу проверить «логику» хранилища, введенную Micronaut-Data в базу данных SQL.

Это для Micronaut Data 1.0.0.M5, использующей Groovy для источника.

Ответы [ 3 ]

0 голосов
/ 06 декабря 2019

После еще нескольких работ я нашел другой способ решить исходную проблему. Вы можете определить базовый класс интерфейса, в котором есть только те методы, которые вам нужны. Затем реализуйте конкретные классы для нужного вам диалекта. Это позволяет использовать один тип БД для тестирования и один для производства.

interface OrderRepository extends BaseRepository, CrudRepository<Order, UUID> {
  @Join(value = "product", type = Join.Type.LEFT_FETCH)
  Optional<Order> findById(UUID uuid)
}

@JdbcRepository(dialect = Dialect.H2)
@Requires(env = ["test"])
interface OrderRepositoryH2 extends OrderRepository, CrudRepository<Order, UUID> {
}

@JdbcRepository(dialect = Dialect.POSTGRES)
@Requires(env = ["dev"])
interface OrderRepositoryPostgres extends OrderRepository, CrudRepository<Order, UUID> {
}

В интерфейсе OrderRepositoryH2 не требуется никаких методов. Micronaut-data использует методы из родительского интерфейса нормально. Хитрость заключается в том, чтобы не использовать аннотацию @JdbcRepository в родительском интерфейсе.

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

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

Извините за путаницу в вопросе и комментариях. (Я решил пометить это как ответ, так как это решает исходную проблему).

0 голосов
/ 10 декабря 2019

Чтобы сделать метод find () доступным в TestBookRepository, мне пришлось повторить метод (см. Прокомментированную строку выше).

Я не могу воспроизвести это поведение. Чтобы это было так, я думаю, что в java-компиляторе должна быть ошибка, которая вызвала это.

См. Проект на https://github.com/jeffbrown/mikehoustonrepository.

https://github.com/jeffbrown/mikehoustonrepository/blob/82b8af568042c762a86cef9965e52fdc61053421/src/main/java/mikehoustonrepository/BookRepository.java

// src/main/java/mikehoustonrepository/BookRepository.java
package mikehoustonrepository;

import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;
import io.micronaut.data.repository.CrudRepository;

import java.util.Optional;

@JdbcRepository(dialect = Dialect.POSTGRES)
public interface BookRepository extends CrudRepository<Book, Long> {
    Optional<Book> find(String title);
}

https://github.com/jeffbrown/mikehoustonrepository/blob/82b8af568042c762a86cef9965e52fdc61053421/src/test/java/mikehoustonrepository/TestBookRepository.java

// src/test/java/mikehoustonrepository/TestBookRepository.java
package mikehoustonrepository;

import io.micronaut.context.annotation.Replaces;
import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;

@JdbcRepository(dialect = Dialect.H2)
@Replaces(BookRepository.class)
public interface TestBookRepository extends BookRepository{}

https://github.com/jeffbrown/mikehoustonrepository/blob/82b8af568042c762a86cef9965e52fdc61053421/src/main/java/mikehoustonrepository/BookController.java

package mikehoustonrepository;

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;

import java.util.Optional;

@Controller("/books")
public class BookController {

    private final BookRepository bookRepository;

    public BookController(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    @Get("/")
    public Iterable<Book> index() {
        return bookRepository.findAll();
    }

    @Post("/{title}/{author}")
    public Book create(String title, String author) {
        return bookRepository.save(new Book(title, author));
    }

    @Get("/find/{title}")
    public Optional<Book> findByTitle(String title) {
        return bookRepository.find(title);
    }
}

https://github.com/jeffbrown/mikehoustonrepository/blob/82b8af568042c762a86cef9965e52fdc61053421/src/test/java/mikehoustonrepository/BookControllerTest.java

package mikehoustonrepository;

import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;

import javax.inject.Inject;
import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

@MicronautTest
public class BookControllerTest {

    @Inject
    BookClient bookClient;

    @Test
    public void testFind() throws Exception {
        Optional<Book> book = bookClient.find("The Nature Of Necessity");
        assertFalse(book.isPresent());

        bookClient.create("The Nature Of Necessity", "Alvin Plantinga");

        book = bookClient.find("The Nature Of Necessity");
        assertTrue(book.isPresent());
    }
}

@Client(value="/", path = "/books")
interface BookClient {
    @Post("/{title}/{author}")
    Book create(String title, String author);

    @Get("/")
    List<Book> list();

    @Get("/find/{title}")
    Optional<Book> find(String title);
}

Этот тест пройден.

Вы можете видеть, что для тестирования используется другой репозиторий (TestBookRepository), который используется для других сред (BookRepository).

Надеюсь, это поможет.

0 голосов
/ 02 декабря 2019

Вы можете использовать среды Micronaut для создания различных конфигураций среды для тестирования и производства, а также для настройки соответствующей конфигурации источника данных в application-test.yml и использовать этот источник данных для тестов

Среды Micronaut из документов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...