Репозитории с нативными запросами не работают в тестовой среде - postgres, jpa, spring - PullRequest
0 голосов
/ 17 июня 2019

Я настроил интеграционные тесты для проекта весенней загрузки, используя тестовые контейнеры (настраивает экземпляр докера с помощью postgresql). Тесты отлично работают, если репозитории, с которыми я тестирую, не используют собственные запросы. Однако всякий раз, когда репозиторий содержит собственный запрос, я получаю следующую ошибку: ERROR: relation "my_table_here" does not exist. Как заставить мою тестовую конфигурацию работать так, чтобы разрешать собственные запросы?

Ниже приведены настройки моего теста:

@RunWith(SpringRunner.class)
public class TestPostgresql {

    @ClassRule
    public static PostgreSQLContainer postgreSQLContainer = PostgresDbContainer.getInstance();

    /**
     * ************ REPOSITORIES ************
     */
    @Autowired
    NativeQueryRepository nativeQueryRepository;

    @TestConfiguration
    @EnableJpaAuditing
    @EnableJpaRepositories(
            basePackageClasses = {
                    NativeQueryRepository.class
            })
    @ComponentScan(
            basePackages = {
                    "com.company.project.package.repository"
            }
    )
    static class PostgresConfiguration {

        /**
         * ************ DATABASE SETUP ************
         */
        @Bean
        public DataSource dataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setUrl(postgreSQLContainer.getJdbcUrl());
            dataSource.setUsername(postgreSQLContainer.getUsername());
            dataSource.setPassword(postgreSQLContainer.getPassword());
            return dataSource;
        }

        @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
            HibernateJpaVendorAdapter vendorAdapter = new JpaVendorAdapter();
            vendorAdapter.setDatabase(Database.POSTGRESQL);
            vendorAdapter.setGenerateDdl(true);

            LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
            factory.setJpaVendorAdapter(vendorAdapter);
            factory.setPackagesToScan("com.company.project");
            factory.setDataSource(dataSource());
            return factory;
        }

        @Bean
        public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
            JpaTransactionManager txManager = new JpaTransactionManager();
            txManager.setEntityManagerFactory(entityManagerFactory);
            return txManager;
        }
    }
}

РЕДАКТИРОВАТЬ: я полагаю, это как-то связано со стратегией именования?

Для большего контекста, вот пример того, как nativeQuery используется в репозитории

@Repository
public interface NativeQueryRepository extends JpaRepository<NativeEvent, Long> {

    @Modifying
    @Transactional
    @Query(value = "UPDATE native_event SET state = :state " +
                    "WHERE secondary_id = :secondaryId", nativeQuery = true)
    void updateState(
            @Param("state") String state,
            @Param("secondaryId") String secondaryId);

}

Я также пытался обновить testProperties для статического класса внутри TestPostgresql, добавив аннотацию:

@TestPropertySource(properties = {
            "spring.jpa.hibernate.naming-strategy=org.springframework.boot.orm.jpa.SpringNamingStrategy"
    })

Однако без изменений получена ошибка.

РЕДАКТИРОВАТЬ: добавить NativeEvent:

@Entity
@Table(
        name = "NativeEvent",
        indexes = {
                @Index(name = "idx_native_event_secondary_id", columnList = "secondaryId")
        }
)
@EntityListeners(AuditingEntityListener.class)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class NativeEvent implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name="secondaryId", nullable=false)
    private String secondaryId;

    @Column(name="state")
    private String state;
}

Ответы [ 2 ]

0 голосов
/ 19 июня 2019

Вы выполняете ручную настройку вместо использования конфигурации времени выполнения.Отсюда иное отношение к стратегиям именования.Вместо этого вы должны повторно использовать ту же конфигурацию, а не писать свою собственную.

Либо используйте @SpringBootTest или @DataJpaTest, но и переконфигурируйте DataSource.

Сделайте что-нибудь с ApplicationContextInitializer, чтобы получить свойства JDBC в ApplicationContext.

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(initializers = {TestPostgresql.JdbcInitializer.class})
public class TestPostgresql {

    @ClassRule
    public static PostgreSQLContainer postgreSQLContainer = PostgresDbContainer.getInstance();

    /**
     * ************ REPOSITORIES ************
     */
    @Autowired
    NativeQueryRepository nativeQueryRepository;

    static class JdbcInitializer
      implements ApplicationContextInitializer<ConfigurableApplicationContext> {
        public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
            TestPropertyValues.of(
              "spring.datasource.url=" + postgreSQLContainer.getJdbcUrl(),
              "spring.datasource.username=" + postgreSQLContainer.getUsername(),
              "spring.datasource.password=" + postgreSQLContainer.getPassword()
            ).applyTo(configurableApplicationContext.getEnvironment());
        }
    }    
}

Это позволит повторно использовать конфигурацию из среды выполнения вашего теста.Вместо @SpringBootTest вы должны также иметь возможность использовать @DataJpaTest(NativeQueryRepository.class), чтобы сделать нарезанный тест только для JPA.

0 голосов
/ 18 июня 2019

Вы присваиваете имя вашей таблицы явно следующим образом:

@Table(name = "NativeEvent")

, но в вашем собственном запросе у вас есть другое имя для этой таблицы:

 @Query(value = "UPDATE native_event ...)

Либо удалите nameатрибут из ваших @Table аннотаций (при условии, что ваша стратегия именования будет производить такие имена, как native_event ) или изменит имя таблицы в собственном запросе на nativeevent или nativeEvent , поэтомув этом случае просто удалите подчеркивание.

Несколько связанных post

...