#163 - Add tests for R2DBC MySQL.

This commit is contained in:
Mark Paluch
2019-08-15 12:22:37 +02:00
parent 6cd08ac64b
commit e15e6b19d4
9 changed files with 305 additions and 22 deletions

28
pom.xml
View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -30,6 +32,7 @@
<postgresql.version>42.2.5</postgresql.version>
<mysql.version>5.1.47</mysql.version>
<jasync.version>0.9.52</jasync.version>
<r2dbc-mysql.version>0.2.0.M2</r2dbc-mysql.version>
<mssql-jdbc.version>7.1.2.jre8-preview</mssql-jdbc.version>
<r2dbc-releasetrain.version>Arabba-M8</r2dbc-releasetrain.version>
<reactive-streams.version>1.0.1</reactive-streams.version>
@@ -171,6 +174,8 @@
<scope>test</scope>
</dependency>
<!-- JDBC Drivers -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
@@ -192,6 +197,8 @@
<scope>test</scope>
</dependency>
<!-- R2DBC Drivers -->
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-postgresql</artifactId>
@@ -218,12 +225,14 @@
</dependency>
<dependency>
<groupId>de.schauderhaft.degraph</groupId>
<artifactId>degraph-check</artifactId>
<version>${degraph-check.version}</version>
<groupId>com.github.mirromutth</groupId>
<artifactId>r2dbc-mysql</artifactId>
<version>${r2dbc-mysql.version}</version>
<scope>test</scope>
</dependency>
<!-- Testcontainers -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mysql</artifactId>
@@ -242,6 +251,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.schauderhaft.degraph</groupId>
<artifactId>degraph-check</artifactId>
<version>${degraph-check.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.mockk</groupId>
<artifactId>mockk</artifactId>
@@ -421,6 +437,10 @@
<id>jcenter</id>
<url>https://jcenter.bintray.com/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<pluginRepositories>

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.r2dbc.core;
import io.r2dbc.spi.ConnectionFactory;
import javax.sql.DataSource;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.data.r2dbc.testing.ExternalDatabase;
import org.springframework.data.r2dbc.testing.MySqlTestSupport;
/**
* Integration tests for {@link DatabaseClient} against MySQL using Jasync MySQL.
*
* @author Mark Paluch
*/
public class JasyncMySqlDatabaseClientIntegrationTests extends AbstractDatabaseClientIntegrationTests {
@ClassRule public static final ExternalDatabase database = MySqlTestSupport.database();
@Override
protected DataSource createDataSource() {
return MySqlTestSupport.createDataSource(database);
}
@Override
protected ConnectionFactory createConnectionFactory() {
return MySqlTestSupport.createJasyncConnectionFactory(database);
}
@Override
protected String getCreateTableStatement() {
return MySqlTestSupport.CREATE_TABLE_LEGOSET;
}
@Override
@Ignore("Jasync currently uses its own exceptions, see jasync-sql/jasync-sql#106")
@Test
public void shouldTranslateDuplicateKeyException() {}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.r2dbc.core;
import io.r2dbc.spi.ConnectionFactory;
import reactor.core.publisher.Mono;
import java.time.Duration;
import javax.sql.DataSource;
import org.junit.ClassRule;
import org.springframework.data.r2dbc.testing.ExternalDatabase;
import org.springframework.data.r2dbc.testing.MySqlTestSupport;
/**
* Transactional integration tests for {@link DatabaseClient} against MySQL using Jasync MySQL.
*
* @author Mark Paluch
*/
public class JasyncMySqlTransactionalDatabaseClientIntegrationTests
extends AbstractTransactionalDatabaseClientIntegrationTests {
@ClassRule public static final ExternalDatabase database = MySqlTestSupport.database();
@Override
protected DataSource createDataSource() {
return MySqlTestSupport.createDataSource(database);
}
@Override
protected ConnectionFactory createConnectionFactory() {
return MySqlTestSupport.createJasyncConnectionFactory(database);
}
@Override
protected String getCreateTableStatement() {
return MySqlTestSupport.CREATE_TABLE_LEGOSET;
}
@Override
protected Mono<Void> prepareForTransaction(DatabaseClient client) {
/*
* We have to execute a sql statement first.
* Otherwise MySql don't have a transaction id.
* And we need to delay emitting the result so that MySql has time to write the transaction id, which is done in
* batches every now and then.
* @see: https://dev.mysql.com/doc/refman/5.7/en/innodb-information-schema-internal-data.html
*/
return client.execute(getInsertIntoLegosetStatement()) //
.bind(0, 42055) //
.bind(1, "SCHAUFELRADBAGGER") //
.bindNull(2, Integer.class) //
.fetch().rowsUpdated() //
.delayElement(Duration.ofMillis(50)) //
.then();
}
@Override
protected String getCurrentTransactionIdStatement() {
return "SELECT tx.trx_id FROM information_schema.innodb_trx tx WHERE tx.trx_mysql_thread_id = connection_id()";
}
}

View File

@@ -20,9 +20,7 @@ import io.r2dbc.spi.ConnectionFactory;
import javax.sql.DataSource;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.testing.ExternalDatabase;
import org.springframework.data.r2dbc.testing.MySqlTestSupport;
@@ -49,10 +47,4 @@ public class MySqlDatabaseClientIntegrationTests extends AbstractDatabaseClientI
protected String getCreateTableStatement() {
return MySqlTestSupport.CREATE_TABLE_LEGOSET;
}
@Override
@Ignore("Jasync currently uses its own exceptions, see jasync-sql/jasync-sql#106")
@Test
public void shouldTranslateDuplicateKeyException() {}
}

View File

@@ -15,17 +15,19 @@
*/
package org.springframework.data.r2dbc.core;
import javax.sql.DataSource;
import io.r2dbc.spi.ConnectionFactory;
import reactor.core.publisher.Mono;
import java.time.Duration;
import io.r2dbc.spi.ConnectionFactory;
import javax.sql.DataSource;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.data.r2dbc.testing.ExternalDatabase;
import org.springframework.data.r2dbc.testing.MySqlTestSupport;
import reactor.core.publisher.Mono;
/**
* Transactional integration tests for {@link DatabaseClient} against MySQL.
@@ -71,6 +73,17 @@ public class MySqlTransactionalDatabaseClientIntegrationTests
.then();
}
@Test
@Ignore("https://github.com/mirromutth/r2dbc-mysql/issues/45")
@Override
public void emitTransactionIds() {}
@Test
@Ignore("https://github.com/mirromutth/r2dbc-mysql/issues/45")
public void emitTransactionIdsUsingManagedTransactions() {
super.emitTransactionIdsUsingManagedTransactions();
}
@Override
protected String getCurrentTransactionIdStatement() {
return "SELECT tx.trx_id FROM information_schema.innodb_trx tx WHERE tx.trx_mysql_thread_id = connection_id()";

View File

@@ -3,6 +3,8 @@ package org.springframework.data.r2dbc.dialect;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import io.github.mirromutth.r2dbc.mysql.MySqlConnectionConfiguration;
import io.github.mirromutth.r2dbc.mysql.MySqlConnectionFactory;
import io.r2dbc.h2.H2ConnectionConfiguration;
import io.r2dbc.h2.H2ConnectionFactory;
import io.r2dbc.mssql.MssqlConnectionConfiguration;
@@ -24,6 +26,7 @@ import org.springframework.data.relational.core.sql.render.SelectRenderContext;
import com.github.jasync.r2dbc.mysql.JasyncConnectionFactory;
import com.github.jasync.sql.db.mysql.pool.MySQLConnectionFactory;
import reactor.core.publisher.Mono;
/**
* Unit tests for {@link DialectResolver}.
@@ -40,11 +43,14 @@ public class DialectResolverUnitTests {
MssqlConnectionFactory mssql = new MssqlConnectionFactory(MssqlConnectionConfiguration.builder().host("localhost")
.database("foo").username("bar").password("password").build());
H2ConnectionFactory h2 = new H2ConnectionFactory(H2ConnectionConfiguration.builder().inMemory("mem").build());
JasyncConnectionFactory mysql = new JasyncConnectionFactory(mock(MySQLConnectionFactory.class));
JasyncConnectionFactory jasyncMysql = new JasyncConnectionFactory(mock(MySQLConnectionFactory.class));
MySqlConnectionFactory mysql = MySqlConnectionFactory
.from(MySqlConnectionConfiguration.builder().host("localhost").username("mysql").build());
assertThat(DialectResolver.getDialect(postgres)).isEqualTo(PostgresDialect.INSTANCE);
assertThat(DialectResolver.getDialect(mssql)).isEqualTo(SqlServerDialect.INSTANCE);
assertThat(DialectResolver.getDialect(h2)).isEqualTo(H2Dialect.INSTANCE);
assertThat(DialectResolver.getDialect(jasyncMysql)).isEqualTo(MySqlDialect.INSTANCE);
assertThat(DialectResolver.getDialect(mysql)).isEqualTo(MySqlDialect.INSTANCE);
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.r2dbc.repository;
import io.r2dbc.spi.ConnectionFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.sql.DataSource;
import org.junit.ClassRule;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
import org.springframework.data.r2dbc.repository.query.Query;
import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory;
import org.springframework.data.r2dbc.testing.ExternalDatabase;
import org.springframework.data.r2dbc.testing.MySqlTestSupport;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Integration tests for {@link LegoSetRepository} using {@link R2dbcRepositoryFactory} against MySQL using Jasync
* MySQL.
*
* @author Mark Paluch
*/
@RunWith(SpringRunner.class)
@ContextConfiguration
public class JasyncMySqlR2dbcRepositoryIntegrationTests extends AbstractR2dbcRepositoryIntegrationTests {
@ClassRule public static final ExternalDatabase database = MySqlTestSupport.database();
@Configuration
@EnableR2dbcRepositories(considerNestedRepositories = true,
includeFilters = @Filter(classes = MySqlLegoSetRepository.class, type = FilterType.ASSIGNABLE_TYPE))
static class IntegrationTestConfiguration extends AbstractR2dbcConfiguration {
@Bean
@Override
public ConnectionFactory connectionFactory() {
return MySqlTestSupport.createJasyncConnectionFactory(database);
}
}
@Override
protected DataSource createDataSource() {
return MySqlTestSupport.createDataSource(database);
}
@Override
protected ConnectionFactory createConnectionFactory() {
return MySqlTestSupport.createJasyncConnectionFactory(database);
}
@Override
protected String getCreateTableStatement() {
return MySqlTestSupport.CREATE_TABLE_LEGOSET_WITH_ID_GENERATION;
}
@Override
protected Class<? extends LegoSetRepository> getRepositoryInterfaceType() {
return MySqlLegoSetRepository.class;
}
interface MySqlLegoSetRepository extends LegoSetRepository {
@Override
@Query("SELECT * FROM legoset WHERE name like ?")
Flux<LegoSet> findByNameContains(String name);
@Override
@Query("SELECT name FROM legoset")
Flux<Named> findAsProjection();
@Override
@Query("SELECT * FROM legoset WHERE manual = :manual")
Mono<LegoSet> findByManual(int manual);
@Override
@Query("SELECT id FROM legoset")
Flux<Integer> findAllIds();
}
}

View File

@@ -48,7 +48,7 @@ abstract class ConnectionUtils {
* @param configuration
* @return
*/
private static ConnectionFactoryOptions createOptions(String driver, ExternalDatabase configuration) {
static ConnectionFactoryOptions createOptions(String driver, ExternalDatabase configuration) {
return ConnectionFactoryOptions.builder().option(DRIVER, driver) //
.option(USER, configuration.getUsername()) //

View File

@@ -15,7 +15,9 @@
*/
package org.springframework.data.r2dbc.testing;
import io.github.mirromutth.r2dbc.mysql.MySqlConnectionFactoryProvider;
import io.r2dbc.spi.ConnectionFactory;
import io.r2dbc.spi.ConnectionFactoryOptions;
import java.util.function.Supplier;
import java.util.stream.Stream;
@@ -26,6 +28,7 @@ import org.springframework.data.r2dbc.testing.ExternalDatabase.ProvidedDatabase;
import org.testcontainers.containers.MySQLContainer;
import com.github.jasync.r2dbc.mysql.MysqlConnectionFactoryProvider;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
/**
@@ -90,7 +93,7 @@ public class MySqlTestSupport {
.port(3306) //
.database("mysql") //
.username("root") //
.password("my-secret-pw").build();
.password("my-secret-pw").jdbcUrl("jdbc:mysql://localhost:3306/mysql").build();
}
/**
@@ -101,7 +104,7 @@ public class MySqlTestSupport {
if (testContainerDatabase == null) {
try {
MySQLContainer container = new MySQLContainer("mysql:5.6.43");
MySQLContainer container = new MySQLContainer();
container.start();
testContainerDatabase = ProvidedDatabase.builder(container) //
@@ -117,10 +120,21 @@ public class MySqlTestSupport {
}
/**
* Creates a new {@link ConnectionFactory} configured from the {@link ExternalDatabase}..
* Creates a new Jasync MySQL {@link ConnectionFactory} configured from the {@link ExternalDatabase}.
*/
public static ConnectionFactory createJasyncConnectionFactory(ExternalDatabase database) {
ConnectionFactoryOptions options = ConnectionUtils.createOptions("mysql", database);
return new MysqlConnectionFactoryProvider().create(options);
}
/**
* Creates a new R2DBC MySQL {@link ConnectionFactory} configured from the {@link ExternalDatabase}.
*/
public static ConnectionFactory createConnectionFactory(ExternalDatabase database) {
return ConnectionUtils.getConnectionFactory("mysql", database);
ConnectionFactoryOptions options = ConnectionUtils.createOptions("mysql", database);
return new MySqlConnectionFactoryProvider().create(options);
}
/**