/** * Copyright 2010-2017 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 * * http://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.mybatis.spring; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Properties; import org.apache.ibatis.cache.impl.PerpetualCache; import org.apache.ibatis.io.JBoss6VFS; import org.apache.ibatis.reflection.factory.DefaultObjectFactory; import org.apache.ibatis.reflection.factory.ObjectFactory; import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory; import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.transaction.TransactionFactory; import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; import org.apache.ibatis.type.TypeAliasRegistry; import org.apache.ibatis.type.TypeException; import org.apache.ibatis.type.TypeHandler; import org.apache.ibatis.type.TypeHandlerRegistry; import org.junit.jupiter.api.Test; import org.mybatis.spring.transaction.SpringManagedTransactionFactory; import org.mybatis.spring.type.DummyTypeAlias; import org.mybatis.spring.type.DummyTypeHandler; import org.mybatis.spring.type.SuperType; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import com.mockrunner.mock.jdbc.MockDataSource; public final class SqlSessionFactoryBeanTest { private static final class TestObjectFactory extends DefaultObjectFactory { private static final long serialVersionUID = 1L;} private static final class TestObjectWrapperFactory extends DefaultObjectWrapperFactory {} private static MockDataSource dataSource = new MockDataSource(); private SqlSessionFactoryBean factoryBean; public void setupFactoryBean() { factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); } @Test public void testDefaults() throws Exception { setupFactoryBean(); assertDefaultConfig(factoryBean.getObject()); } // DataSource is the only required property that does not have a default value, so test for both // not setting it at all and setting it to null @Test public void testNullDataSource() throws Exception { factoryBean = new SqlSessionFactoryBean(); assertThrows(IllegalArgumentException.class, factoryBean::getObject); } @Test public void testSetNullDataSource() throws Exception { factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(null); assertThrows(IllegalArgumentException.class, factoryBean::getObject); } @Test public void testNullSqlSessionFactoryBuilder() throws Exception { setupFactoryBean(); factoryBean.setSqlSessionFactoryBuilder(null); assertThrows(IllegalArgumentException.class, factoryBean::getObject); } @Test public void testNullTransactionFactoryClass() throws Exception { setupFactoryBean(); factoryBean.setTransactionFactory(null); assertConfig(factoryBean.getObject(), SpringManagedTransactionFactory.class); } @Test public void testOtherTransactionFactoryClass() throws Exception { setupFactoryBean(); factoryBean.setTransactionFactory(new JdbcTransactionFactory()); assertConfig(factoryBean.getObject(), JdbcTransactionFactory.class); } @Test public void testEmptyStringEnvironment() throws Exception { setupFactoryBean(); factoryBean.setEnvironment(""); assertConfig(factoryBean.getObject(), "", org.mybatis.spring.transaction.SpringManagedTransactionFactory.class); } @Test public void testDefaultConfiguration() throws Exception { setupFactoryBean(); assertDefaultConfig(factoryBean.getObject()); } @Test public void testDefaultConfigurationWithConfigurationProperties() throws Exception { setupFactoryBean(); Properties configurationProperties = new Properties(); configurationProperties.put("username", "dev"); factoryBean.setConfigurationProperties(configurationProperties); SqlSessionFactory factory = factoryBean.getObject(); assertConfig(factory, SpringManagedTransactionFactory.class); assertThat(factory.getConfiguration().getVariables().size()).isEqualTo(1); assertThat(factory.getConfiguration().getVariables().get("username")).isEqualTo("dev"); } @Test public void testSetConfiguration() throws Exception { setupFactoryBean(); Configuration customConfiguration = new Configuration(); customConfiguration.setCacheEnabled(false); customConfiguration.setUseGeneratedKeys(true); customConfiguration.setDefaultExecutorType(ExecutorType.REUSE); customConfiguration.setVfsImpl(JBoss6VFS.class); factoryBean.setConfiguration(customConfiguration); SqlSessionFactory factory = factoryBean.getObject(); assertThat(factory.getConfiguration().getEnvironment().getId()).isEqualTo(SqlSessionFactoryBean.class.getSimpleName()); assertThat(factory.getConfiguration().getEnvironment().getDataSource()).isSameAs(dataSource); assertThat(factory.getConfiguration().getEnvironment().getTransactionFactory().getClass()).isSameAs(SpringManagedTransactionFactory.class); assertThat(factory.getConfiguration().getVfsImpl()).isSameAs(JBoss6VFS.class); assertThat(factory.getConfiguration().isCacheEnabled()).isFalse(); assertThat(factory.getConfiguration().isUseGeneratedKeys()).isTrue(); assertThat(factory.getConfiguration().getDefaultExecutorType()).isSameAs(ExecutorType.REUSE); } @Test public void testSpecifyVariablesOnly() throws Exception { setupFactoryBean(); Configuration customConfiguration = new Configuration(); Properties variables = new Properties(); variables.put("username", "sa"); customConfiguration.setVariables(variables); factoryBean.setConfiguration(customConfiguration); factoryBean.setConfigurationProperties(null); SqlSessionFactory factory = factoryBean.getObject(); assertThat(factory.getConfiguration().getVariables().size()).isEqualTo(1); assertThat(factory.getConfiguration().getVariables().get("username")).isEqualTo("sa"); } @Test public void testSpecifyVariablesAndConfigurationProperties() throws Exception { setupFactoryBean(); Configuration customConfiguration = new Configuration(); Properties variables = new Properties(); variables.put("url", "jdbc:localhost/test"); variables.put("username", "sa"); customConfiguration.setVariables(variables); factoryBean.setConfiguration(customConfiguration); Properties configurationProperties = new Properties(); configurationProperties.put("username", "dev"); configurationProperties.put("password", "Passw0rd"); factoryBean.setConfigurationProperties(configurationProperties); SqlSessionFactory factory = factoryBean.getObject(); assertThat(factory.getConfiguration().getVariables().size()).isEqualTo(3); assertThat(factory.getConfiguration().getVariables().get("url")).isEqualTo("jdbc:localhost/test"); assertThat(factory.getConfiguration().getVariables().get("username")).isEqualTo("dev"); assertThat(factory.getConfiguration().getVariables().get("password")).isEqualTo("Passw0rd"); } @Test public void testSpecifyConfigurationPropertiesOnly() throws Exception { setupFactoryBean(); Configuration customConfiguration = new Configuration(); customConfiguration.setVariables(null); factoryBean.setConfiguration(customConfiguration); Properties configurationProperties = new Properties(); configurationProperties.put("username", "dev"); factoryBean.setConfigurationProperties(configurationProperties); SqlSessionFactory factory = factoryBean.getObject(); assertThat(factory.getConfiguration().getVariables().size()).isEqualTo(1); assertThat(factory.getConfiguration().getVariables().get("username")).isEqualTo("dev"); } @Test public void testNotSpecifyVariableAndConfigurationProperties() throws Exception { setupFactoryBean(); Configuration customConfiguration = new Configuration(); customConfiguration.setVariables(null); factoryBean.setConfiguration(customConfiguration); factoryBean.setConfigurationProperties(null); SqlSessionFactory factory = factoryBean.getObject(); assertThat(factory.getConfiguration().getVariables()).isNull(); } @Test public void testNullConfigLocation() throws Exception { setupFactoryBean(); // default should also be null, but test explicitly setting to null factoryBean.setConfigLocation(null); assertDefaultConfig(factoryBean.getObject()); } @Test public void testSetConfigLocation() throws Exception { setupFactoryBean(); factoryBean.setConfigLocation(new org.springframework.core.io.ClassPathResource( "org/mybatis/spring/mybatis-config.xml")); SqlSessionFactory factory = factoryBean.getObject(); assertThat(factory.getConfiguration().getEnvironment().getId()).isEqualTo(SqlSessionFactoryBean.class.getSimpleName()); assertThat(factory.getConfiguration().getEnvironment().getDataSource()).isSameAs(dataSource); assertThat(factory.getConfiguration().getEnvironment().getTransactionFactory().getClass()) .isSameAs(org.mybatis.spring.transaction.SpringManagedTransactionFactory.class); assertThat(factory.getConfiguration().getVfsImpl()).isSameAs(JBoss6VFS.class); // properties explicitly set differently than the defaults in the config xml assertThat(factory.getConfiguration().isCacheEnabled()).isFalse(); assertThat(factory.getConfiguration().isUseGeneratedKeys()).isTrue(); assertThat(factory.getConfiguration().getDefaultExecutorType()).isSameAs(org.apache.ibatis.session.ExecutorType.REUSE); // for each statement in the xml file: org.mybatis.spring.TestMapper.xxx & xxx assertThat(factory.getConfiguration().getMappedStatementNames().size()).isEqualTo(8); assertThat(factory.getConfiguration().getResultMapNames().size()).isEqualTo(0); assertThat(factory.getConfiguration().getParameterMapNames().size()).isEqualTo(0); } @Test public void testSpecifyConfigurationAndConfigLocation() throws Exception { setupFactoryBean(); factoryBean.setConfiguration(new Configuration()); factoryBean.setConfigLocation(new org.springframework.core.io.ClassPathResource( "org/mybatis/spring/mybatis-config.xml")); Throwable e = assertThrows(IllegalStateException.class, factoryBean::getObject); assertThat(e.getMessage()).isEqualTo("Property 'configuration' and 'configLocation' can not specified with together"); } @Test public void testFragmentsAreReadWithMapperLocations() throws Exception { setupFactoryBean(); factoryBean.setMapperLocations(new Resource[] { new ClassPathResource("org/mybatis/spring/TestMapper.xml") }); SqlSessionFactory factory = factoryBean.getObject(); // one for 'includedSql' and another for 'org.mybatis.spring.TestMapper.includedSql' assertThat(factory.getConfiguration().getSqlFragments().size()).isEqualTo(2); } @Test public void testNullMapperLocations() throws Exception { setupFactoryBean(); // default should also be null, but test explicitly setting to null factoryBean.setMapperLocations(null); assertDefaultConfig(factoryBean.getObject()); } @Test public void testEmptyMapperLocations() throws Exception { setupFactoryBean(); factoryBean.setMapperLocations(new org.springframework.core.io.Resource[0]); assertDefaultConfig(factoryBean.getObject()); } @Test public void testMapperLocationsWithNullEntry() throws Exception { setupFactoryBean(); factoryBean.setMapperLocations(new org.springframework.core.io.Resource[] { null }); assertDefaultConfig(factoryBean.getObject()); } @Test public void testAddATypeHandler() throws Exception { setupFactoryBean(); factoryBean.setTypeHandlers(new TypeHandler[] { new DummyTypeHandler() }); TypeHandlerRegistry typeHandlerRegistry = factoryBean.getObject().getConfiguration().getTypeHandlerRegistry(); assertThat(typeHandlerRegistry.hasTypeHandler(BigInteger.class)).isTrue(); } @Test public void testAddATypeAlias() throws Exception { setupFactoryBean(); factoryBean.setTypeAliases(new Class[] { DummyTypeAlias.class }); TypeAliasRegistry typeAliasRegistry = factoryBean.getObject().getConfiguration().getTypeAliasRegistry(); typeAliasRegistry.resolveAlias("testAlias"); } @Test public void testSearchATypeAliasPackage() throws Exception { setupFactoryBean(); factoryBean.setTypeAliasesPackage("org/mybatis/spring/type"); TypeAliasRegistry typeAliasRegistry = factoryBean.getObject().getConfiguration().getTypeAliasRegistry(); typeAliasRegistry.resolveAlias("testAlias"); typeAliasRegistry.resolveAlias("testAlias2"); typeAliasRegistry.resolveAlias("dummyTypeHandler"); typeAliasRegistry.resolveAlias("superType"); } @Test public void testSearchATypeAliasPackageWithSuperType() throws Exception { setupFactoryBean(); factoryBean.setTypeAliasesSuperType(SuperType.class); factoryBean.setTypeAliasesPackage("org/mybatis/spring/type"); TypeAliasRegistry typeAliasRegistry = factoryBean.getObject().getConfiguration().getTypeAliasRegistry(); typeAliasRegistry.resolveAlias("testAlias2"); typeAliasRegistry.resolveAlias("superType"); assertThrows(TypeException.class, () -> typeAliasRegistry.resolveAlias("testAlias")); assertThrows(TypeException.class, () -> typeAliasRegistry.resolveAlias("dummyTypeHandler")); } @Test public void testSearchATypeHandlerPackage() throws Exception { setupFactoryBean(); factoryBean.setTypeHandlersPackage("org/mybatis/spring/type"); TypeHandlerRegistry typeHandlerRegistry = factoryBean.getObject().getConfiguration().getTypeHandlerRegistry(); assertThat(typeHandlerRegistry.hasTypeHandler(BigInteger.class)).isTrue(); assertThat(typeHandlerRegistry.hasTypeHandler(BigDecimal.class)).isTrue(); } @Test public void testSetObjectFactory() throws Exception { setupFactoryBean(); factoryBean.setObjectFactory(new TestObjectFactory()); ObjectFactory objectFactory = factoryBean.getObject().getConfiguration().getObjectFactory(); assertThat(objectFactory).isInstanceOf(TestObjectFactory.class); } @Test public void testSetObjectWrapperFactory() throws Exception { setupFactoryBean(); factoryBean.setObjectWrapperFactory(new TestObjectWrapperFactory()); ObjectWrapperFactory objectWrapperFactory = factoryBean.getObject().getConfiguration().getObjectWrapperFactory(); assertThat(objectWrapperFactory).isInstanceOf(TestObjectWrapperFactory.class); } @Test public void testAddCache() { setupFactoryBean(); PerpetualCache cache = new PerpetualCache("test-cache"); this.factoryBean.setCache(cache); assertThat(this.factoryBean.getCache().getId()).isEqualTo("test-cache"); } private void assertDefaultConfig(SqlSessionFactory factory) { assertConfig(factory, SqlSessionFactoryBean.class.getSimpleName(), org.mybatis.spring.transaction.SpringManagedTransactionFactory.class); assertThat(factory.getConfiguration().getVariables().size()).isEqualTo(0); } private void assertConfig(SqlSessionFactory factory, Class<? extends TransactionFactory> transactionFactoryClass) { assertConfig(factory, SqlSessionFactoryBean.class.getSimpleName(), transactionFactoryClass); } private void assertConfig(SqlSessionFactory factory, String environment, Class<? extends TransactionFactory> transactionFactoryClass) { assertThat(factory.getConfiguration().getEnvironment().getId()).isEqualTo(environment); assertThat(factory.getConfiguration().getEnvironment().getDataSource()).isSameAs(dataSource); assertThat(factory.getConfiguration().getEnvironment().getTransactionFactory().getClass()).isSameAs(transactionFactoryClass); // no mappers configured => no mapped statements or other parsed elements assertThat(factory.getConfiguration().getMappedStatementNames().size()).isEqualTo(0); assertThat(factory.getConfiguration().getResultMapNames().size()).isEqualTo(0); assertThat(factory.getConfiguration().getParameterMapNames().size()).isEqualTo(0); assertThat(factory.getConfiguration().getSqlFragments().size()).isEqualTo(0); } }