package org.jooby.jooq; import static com.typesafe.config.ConfigValueFactory.fromAnyRef; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.isA; import static org.junit.Assert.assertEquals; import java.util.Properties; import javax.inject.Provider; import javax.sql.DataSource; import org.jooby.Env; import org.jooby.test.MockUnit; import org.jooby.test.MockUnit.Block; import org.jooq.Configuration; import org.jooq.ConnectionProvider; import org.jooq.DSLContext; import org.jooq.SQLDialect; import org.jooq.impl.DSL; import org.jooq.impl.DataSourceConnectionProvider; import org.jooq.impl.DefaultConfiguration; import org.jooq.impl.DefaultTransactionProvider; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.name.Names; import com.typesafe.config.Config; import com.typesafe.config.ConfigValueFactory; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import javaslang.control.Try.CheckedRunnable; @RunWith(PowerMockRunner.class) @PrepareForTest({jOOQ.class, DefaultConfiguration.class, DSL.class, DataSourceConnectionProvider.class, DefaultTransactionProvider.class }) public class jOOQTest { @SuppressWarnings("unchecked") private MockUnit.Block configuration = unit -> { DataSourceConnectionProvider dscp = unit.constructor(DataSourceConnectionProvider.class) .build(unit.get(HikariDataSource.class)); DefaultTransactionProvider trx = unit.constructor(DefaultTransactionProvider.class) .args(ConnectionProvider.class) .build(dscp); DefaultConfiguration conf = unit.constructor(DefaultConfiguration.class) .build(); expect(conf.set(dscp)).andReturn(conf); expect(conf.set(trx)).andReturn(conf); expect(conf.set(SQLDialect.H2)).andReturn(conf); unit.registerMock(Configuration.class, conf); AnnotatedBindingBuilder<Configuration> abbC = unit.mock(AnnotatedBindingBuilder.class); abbC.toInstance(conf); abbC.toInstance(conf); Binder binder = unit.get(Binder.class); expect(binder.bind(Key.get(Configuration.class))).andReturn(abbC); expect(binder.bind(Key.get(Configuration.class, Names.named("jdbctest")))).andReturn(abbC); }; @SuppressWarnings("unchecked") private MockUnit.Block ctx = unit -> { DSLContext dslcontext = unit.mock(DSLContext.class); Configuration conf = unit.get(Configuration.class); unit.mockStatic(DSL.class); expect(DSL.using(conf)).andReturn(dslcontext); AnnotatedBindingBuilder<DSLContext> abbC = unit.mock(AnnotatedBindingBuilder.class); expect(abbC.toProvider(isA(Provider.class))).andReturn(abbC); expect(abbC.toProvider(unit.capture(Provider.class))).andReturn(abbC); Binder binder = unit.get(Binder.class); expect(binder.bind(Key.get(DSLContext.class))).andReturn(abbC); expect(binder.bind(Key.get(DSLContext.class, Names.named("jdbctest")))).andReturn(abbC); }; private MockUnit.Block onStop = unit -> { Env env = unit.get(Env.class); expect(env.onStop(isA(CheckedRunnable.class))).andReturn(env); }; @Test public void defaults() throws Exception { String url = "jdbc:h2:target/jdbctest"; new MockUnit(Env.class, Config.class, Binder.class) .expect(props("org.h2.jdbcx.JdbcDataSource", url, "h2.jdbctest", "sa", "", false)) .expect(hikariConfig()) .expect(hikariDataSource(url)) .expect(serviceKey("jdbctest")) .expect(configuration) .expect(ctx) .expect(onStop) .run(unit -> { new jOOQ() .configure(unit.get(Env.class), config(), unit.get(Binder.class)); }, unit -> { unit.captured(Provider.class).iterator().next().get(); }); } @Test public void withDbProp() throws Exception { String url = "jdbc:h2:target/jdbctest"; new MockUnit(Env.class, Config.class, Binder.class) .expect(props("org.h2.jdbcx.JdbcDataSource", url, "h2.jdbctest", "sa", "", false)) .expect(hikariConfig()) .expect(hikariDataSource(url)) .expect(serviceKey("jdbctest")) .expect(configuration) .expect(ctx) .expect(onStop) .run(unit -> { new jOOQ("db") .configure(unit.get(Env.class), config(), unit.get(Binder.class)); }, unit -> { unit.captured(Provider.class).iterator().next().get(); }); } @Test public void doWith() throws Exception { String url = "jdbc:h2:target/jdbctest"; new MockUnit(Env.class, Config.class, Binder.class) .expect(props("org.h2.jdbcx.JdbcDataSource", url, "h2.jdbctest", "sa", "", false)) .expect(hikariConfig()) .expect(hikariDataSource(url)) .expect(serviceKey("jdbctest")) .expect(configuration) .expect(ctx) .expect(onStop) .run(unit -> { new jOOQ() .doWith((final Configuration c) -> assertEquals(unit.get(Configuration.class), c)) .configure(unit.get(Env.class), config(), unit.get(Binder.class)); }, unit -> { unit.captured(Provider.class).iterator().next().get(); }); } private Config config() { return new jOOQ().config() .withValue("db", ConfigValueFactory.fromAnyRef("fs")) .withValue("application.ns", ConfigValueFactory.fromAnyRef("my.model")) .withValue("application.tmpdir", ConfigValueFactory.fromAnyRef("target")) .withValue("application.name", ConfigValueFactory.fromAnyRef("jdbctest")) .withValue("application.charset", ConfigValueFactory.fromAnyRef("UTF-8")) .withValue("runtime.processors-x2", fromAnyRef("4")) .resolve(); } @SuppressWarnings("unchecked") private Block serviceKey(final String db) { return unit -> { Env env = unit.get(Env.class); expect(env.serviceKey()).andReturn(new Env.ServiceKey()).times(2); AnnotatedBindingBuilder<DataSource> binding = unit.mock(AnnotatedBindingBuilder.class); binding.toInstance(unit.get(HikariDataSource.class)); binding.toInstance(unit.get(HikariDataSource.class)); Binder binder = unit.get(Binder.class); expect(binder.bind(Key.get(DataSource.class))).andReturn(binding); expect(binder.bind(Key.get(DataSource.class, Names.named(db)))).andReturn(binding); }; } private Block hikariConfig() { return unit -> { Properties properties = unit.get(Properties.class); HikariConfig hikari = unit.constructor(HikariConfig.class) .build(properties); unit.registerMock(HikariConfig.class, hikari); }; } private Block hikariDataSource(final String url) { return unit -> { HikariConfig properties = unit.get(HikariConfig.class); HikariDataSource hikari = unit.constructor(HikariDataSource.class) .build(properties); Properties props = unit.mock(Properties.class); expect(props.getProperty("url")).andReturn(url); expect(hikari.getDataSourceProperties()).andReturn(props); unit.registerMock(HikariDataSource.class, hikari); }; } private Block props(final String dataSourceClassName, final String url, final String name, final String username, final String password, final boolean hasDataSourceClassName) { return unit -> { Properties properties = unit.constructor(Properties.class) .build(); expect(properties .setProperty("dataSource.dataSourceClassName", dataSourceClassName)) .andReturn(null); if (username != null) { expect(properties .setProperty("dataSource.user", username)) .andReturn(null); expect(properties .setProperty("dataSource.password", password)) .andReturn(null); } expect(properties .setProperty("dataSource.url", url)) .andReturn(null); if (hasDataSourceClassName) { expect(properties.getProperty("dataSourceClassName")).andReturn(dataSourceClassName); } else { expect(properties.getProperty("dataSourceClassName")).andReturn(null); expect(properties.getProperty("dataSource.dataSourceClassName")) .andReturn(dataSourceClassName); expect(properties.setProperty("dataSourceClassName", dataSourceClassName)).andReturn(null); } expect(properties.remove("dataSource.dataSourceClassName")).andReturn(dataSourceClassName); expect(properties.setProperty("poolName", name)).andReturn(null); expect(properties.setProperty("maximumPoolSize", "4")).andReturn(null); unit.registerMock(Properties.class, properties); }; } }