org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfigurationTest.java Source code

Java tutorial

Introduction

Here is the source code for org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfigurationTest.java

Source

/**
 *    Copyright 2015-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
 *
 *       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.boot.autoconfigure;

import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.session.Configuration;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.parser.node.Node;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver;
import org.mybatis.scripting.freemarker.FreeMarkerLanguageDriverConfig;
import org.mybatis.scripting.thymeleaf.TemplateEngineCustomizer;
import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriver;
import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriverConfig;
import org.mybatis.scripting.velocity.VelocityFacade;
import org.mybatis.scripting.velocity.VelocityLanguageDriver;
import org.mybatis.scripting.velocity.VelocityLanguageDriverConfig;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.thymeleaf.TemplateEngine;

import static org.assertj.core.api.Assertions.assertThat;

/**
 * Tests for {@link MybatisLanguageDriverAutoConfiguration}.
 *
 * @author Kazuki Shimizu
 */
class MybatisLanguageDriverAutoConfigurationTest {

    private AnnotationConfigApplicationContext context;

    @BeforeEach
    void init() {
        VelocityFacade.destroy();
        this.context = new AnnotationConfigApplicationContext();
    }

    @AfterEach
    void closeContext() {
        if (this.context != null) {
            this.context.close();
        }
        VelocityFacade.destroy();
    }

    @Test
    void testDefaultConfiguration() {
        this.context.register(MybatisLanguageDriverAutoConfiguration.class);
        this.context.refresh();
        Map<String, LanguageDriver> languageDriverBeans = this.context.getBeansOfType(LanguageDriver.class);
        assertThat(languageDriverBeans).hasSize(3).containsKeys("freeMarkerLanguageDriver",
                "velocityLanguageDriver", "thymeleafLanguageDriver");
        assertThat(languageDriverBeans.get("freeMarkerLanguageDriver"))
                .isInstanceOf(FreeMarkerLanguageDriver.class);
        assertThat(languageDriverBeans.get("velocityLanguageDriver")).isInstanceOf(VelocityLanguageDriver.class);
        assertThat(languageDriverBeans.get("thymeleafLanguageDriver")).isInstanceOf(ThymeleafLanguageDriver.class);
        {
            ThymeleafLanguageDriverConfig config = this.context.getBean(ThymeleafLanguageDriverConfig.class);
            assertThat(config.isUse2way()).isEqualTo(true);
            assertThat(config.getDialect().getPrefix()).isEqualTo("mb");
            assertThat(config.getDialect().getLikeAdditionalEscapeTargetChars()).isNull();
            assertThat(config.getDialect().getLikeEscapeChar()).isEqualTo('\\');
            assertThat(config.getDialect().getLikeEscapeClauseFormat()).isEqualTo("ESCAPE '%s'");
            assertThat(config.getTemplateFile().getBaseDir()).isEqualTo("");
            assertThat(config.getTemplateFile().getCacheTtl()).isNull();
            assertThat(config.getTemplateFile().getEncoding()).isEqualTo(StandardCharsets.UTF_8);
            assertThat(config.getTemplateFile().getPatterns()).hasSize(1).contains("*.sql");
            assertThat(config.getCustomizer()).isNull();
        }
        {
            FreeMarkerLanguageDriverConfig config = this.context.getBean(FreeMarkerLanguageDriverConfig.class);
            assertThat(config.getBasePackage()).isEqualTo("");
            assertThat(config.getFreemarkerSettings()).isEmpty();
        }
        {
            VelocityLanguageDriverConfig config = this.context.getBean(VelocityLanguageDriverConfig.class);
            @SuppressWarnings("deprecation")
            String[] userDirective = config.getUserdirective();
            assertThat(userDirective).hasSize(0);
            assertThat(config.getAdditionalContextAttributes()).hasSize(0);
            assertThat(config.getVelocitySettings()).hasSize(2);
            assertThat(config.getVelocitySettings().get(RuntimeConstants.RESOURCE_LOADERS)).isEqualTo("class");
            assertThat(config.getVelocitySettings().get(RuntimeConstants.RESOURCE_LOADER + ".class.class"))
                    .isEqualTo("org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
            assertThat(config.generateCustomDirectivesString()).isEqualTo(
                    "org.mybatis.scripting.velocity.TrimDirective,org.mybatis.scripting.velocity.WhereDirective,org.mybatis.scripting.velocity.SetDirective,org.mybatis.scripting.velocity.InDirective,org.mybatis.scripting.velocity.RepeatDirective");
        }
    }

    @Test
    void testCustomConfiguration() {
        this.context.register(MyLanguageDriverConfig.class, MybatisLanguageDriverAutoConfiguration.class);
        this.context.refresh();
        Map<String, LanguageDriver> languageDriverBeans = this.context.getBeansOfType(LanguageDriver.class);
        assertThat(languageDriverBeans).hasSize(3).containsKeys("myFreeMarkerLanguageDriver",
                "myVelocityLanguageDriver", "myThymeleafLanguageDriver");
    }

    @Test
    @SuppressWarnings("deprecation")
    void testLegacyConfiguration() {
        this.context.register(TestingLegacyFreeMarkerConfiguration.class, TestingLegacyVelocityConfiguration.class);
        this.context.refresh();
        Map<String, LanguageDriver> languageDriverBeans = this.context.getBeansOfType(LanguageDriver.class);
        assertThat(languageDriverBeans).hasSize(2).containsKeys("freeMarkerLanguageDriver",
                "velocityLanguageDriver");
        assertThat(this.context.getBean(org.mybatis.scripting.velocity.Driver.class)).isNotNull();
        assertThat(this.context.getBean(FreeMarkerLanguageDriver.class)).isNotNull();
        assertThat(this.context.getBeanNamesForType(VelocityLanguageDriverConfig.class)).hasSize(0);
        assertThat(this.context.getBeanNamesForType(FreeMarkerLanguageDriverConfig.class)).hasSize(0);
    }

    @Test
    void testCustomThymeleafConfig() {
        this.context.register(ThymeleafCustomLanguageDriverConfig.class,
                MybatisLanguageDriverAutoConfiguration.class);
        this.context.refresh();
        ThymeleafLanguageDriver driver = this.context.getBean(ThymeleafLanguageDriver.class);
        SqlSource sqlSource = driver.createSqlSource(new Configuration(),
                "SELECT * FROM users WHERE id = /*[# m:p='id']*/ 1 /*[/]*/", Integer.class);
        BoundSql boundSql = sqlSource.getBoundSql(10);
        assertThat(boundSql.getSql()).isEqualTo("SELECT * FROM users WHERE id = ?");
        assertThat(boundSql.getParameterObject()).isEqualTo(10);
        assertThat(boundSql.getParameterMappings().get(0).getProperty()).isEqualTo("id");
        assertThat(boundSql.getParameterMappings().get(0).getJavaType()).isEqualTo(Integer.class);
        ThymeleafLanguageDriverConfig config = this.context.getBean(ThymeleafLanguageDriverConfig.class);
        assertThat(config.isUse2way()).isEqualTo(true);
        assertThat(config.getDialect().getPrefix()).isEqualTo("m");
        assertThat(config.getDialect().getLikeAdditionalEscapeTargetChars()).isNull();
        assertThat(config.getDialect().getLikeEscapeChar()).isEqualTo('\\');
        assertThat(config.getDialect().getLikeEscapeClauseFormat()).isEqualTo("ESCAPE '%s'");
        assertThat(config.getTemplateFile().getBaseDir()).isEqualTo("");
        assertThat(config.getTemplateFile().getCacheTtl()).isNull();
        assertThat(config.getTemplateFile().getEncoding()).isEqualTo(StandardCharsets.UTF_8);
        assertThat(config.getTemplateFile().getPatterns()).hasSize(1).contains("*.sql");
        assertThat(config.getCustomizer()).isNull();
    }

    @Test
    void test() {
        this.context.register(FreeMarkerCustomLanguageDriverConfig.class,
                MybatisLanguageDriverAutoConfiguration.class);
        this.context.refresh();
    }

    @Test
    void testCustomFreeMarkerConfig() {
        this.context.register(FreeMarkerCustomLanguageDriverConfig.class,
                MybatisLanguageDriverAutoConfiguration.class);
        this.context.refresh();
        FreeMarkerLanguageDriver driver = this.context.getBean(FreeMarkerLanguageDriver.class);
        @SuppressWarnings("unused")
        class Param {
            private Integer id;
            private Integer version;
        }
        Param params = new Param();
        params.id = 10;
        params.version = 20;
        SqlSource sqlSource = driver.createSqlSource(new Configuration(),
                "SELECT * FROM users WHERE id = #{id} and version = <@p name='version'/>", Param.class);
        BoundSql boundSql = sqlSource.getBoundSql(params);
        assertThat(boundSql.getSql()).isEqualTo("SELECT * FROM users WHERE id = ? and version = ?");
        assertThat(boundSql.getParameterMappings().get(0).getProperty()).isEqualTo("id");
        assertThat(boundSql.getParameterMappings().get(0).getJavaType()).isEqualTo(Integer.class);
        assertThat(boundSql.getParameterMappings().get(1).getProperty()).isEqualTo("version");
        assertThat(boundSql.getParameterMappings().get(1).getJavaType()).isEqualTo(Integer.class);
        FreeMarkerLanguageDriverConfig config = this.context.getBean(FreeMarkerLanguageDriverConfig.class);
        assertThat(config.getBasePackage()).isEqualTo("");
        assertThat(config.getFreemarkerSettings()).hasSize(1);
        assertThat(config.getFreemarkerSettings().get("interpolation_syntax")).isEqualTo("dollar");
    }

    @Test
    void testCustomVelocityConfig() {
        this.context.register(VelocityCustomLanguageDriverConfig.class,
                MybatisLanguageDriverAutoConfiguration.class);
        this.context.refresh();
        VelocityLanguageDriver driver = this.context.getBean(VelocityLanguageDriver.class);
        @SuppressWarnings("unused")
        class Param {
            private Integer id;
            private Integer version;
        }
        Param params = new Param();
        params.id = 10;
        params.version = 20;
        SqlSource sqlSource = driver.createSqlSource(new Configuration(), "#now()", Param.class);
        BoundSql boundSql = sqlSource.getBoundSql(params);
        assertThat(boundSql.getSql()).isEqualTo("SELECT CURRENT_TIMESTAMP");
        VelocityLanguageDriverConfig config = this.context.getBean(VelocityLanguageDriverConfig.class);
        @SuppressWarnings("deprecation")
        String[] userDirective = config.getUserdirective();
        assertThat(userDirective).hasSize(0);
        assertThat(config.getAdditionalContextAttributes()).hasSize(0);
        assertThat(config.getVelocitySettings()).hasSize(3);
        assertThat(config.getVelocitySettings().get(RuntimeConstants.RESOURCE_LOADERS)).isEqualTo("class");
        assertThat(config.getVelocitySettings().get(RuntimeConstants.RESOURCE_LOADER + ".class.class"))
                .isEqualTo("org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        assertThat(config.generateCustomDirectivesString()).isEqualTo(NowDirective.class.getName()
                + ",org.mybatis.scripting.velocity.TrimDirective,org.mybatis.scripting.velocity.WhereDirective,org.mybatis.scripting.velocity.SetDirective,org.mybatis.scripting.velocity.InDirective,org.mybatis.scripting.velocity.RepeatDirective");
    }

    @Test
    void testCustomThymeleafConfigUsingConfigurationProperty() {
        TestPropertyValues.of("mybatis.scripting-language-driver.thymeleaf.use2way=false",
                "mybatis.scripting-language-driver.thymeleaf.dialect.like-additional-escape-target-chars=*,?",
                "mybatis.scripting-language-driver.thymeleaf.dialect.like-escape-char=~",
                "mybatis.scripting-language-driver.thymeleaf.dialect.like-escape-clause-format=escape '%s'",
                "mybatis.scripting-language-driver.thymeleaf.dialect.prefix=mybatis",
                "mybatis.scripting-language-driver.thymeleaf.template-file.base-dir=sqls",
                "mybatis.scripting-language-driver.thymeleaf.template-file.cache-enabled=false",
                "mybatis.scripting-language-driver.thymeleaf.template-file.cache-ttl=1234",
                "mybatis.scripting-language-driver.thymeleaf.template-file.encoding=Windows-31J",
                "mybatis.scripting-language-driver.thymeleaf.template-file.patterns=*.sql,*.sqlf",
                "mybatis.scripting-language-driver.thymeleaf.customizer=org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfigurationTest$MyTemplateEngineCustomizer")
                .applyTo(this.context);
        this.context.register(MyAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class);
        this.context.refresh();
        ThymeleafLanguageDriver driver = this.context.getBean(ThymeleafLanguageDriver.class);
        SqlSource sqlSource = driver.createSqlSource(new Configuration(),
                "SELECT * FROM users WHERE id = [# mybatis:p='id' /]", Integer.class);
        BoundSql boundSql = sqlSource.getBoundSql(10);
        assertThat(boundSql.getSql()).isEqualTo("SELECT * FROM users WHERE id = ?");
        assertThat(boundSql.getParameterObject()).isEqualTo(10);
        assertThat(boundSql.getParameterMappings().get(0).getProperty()).isEqualTo("id");
        assertThat(boundSql.getParameterMappings().get(0).getJavaType()).isEqualTo(Integer.class);
        ThymeleafLanguageDriverConfig config = this.context.getBean(ThymeleafLanguageDriverConfig.class);
        assertThat(config.isUse2way()).isEqualTo(false);
        assertThat(config.getDialect().getPrefix()).isEqualTo("mybatis");
        assertThat(config.getDialect().getLikeAdditionalEscapeTargetChars()).hasSize(2).contains('*', '?');
        assertThat(config.getDialect().getLikeEscapeChar()).isEqualTo('~');
        assertThat(config.getDialect().getLikeEscapeClauseFormat()).isEqualTo("escape '%s'");
        assertThat(config.getTemplateFile().getBaseDir()).isEqualTo("sqls");
        assertThat(config.getTemplateFile().getCacheTtl()).isEqualTo(1234);
        assertThat(config.getTemplateFile().getEncoding()).isEqualTo(Charset.forName("Windows-31J"));
        assertThat(config.getTemplateFile().getPatterns()).hasSize(2).contains("*.sql", "*.sqlf");
        assertThat(config.getCustomizer()).isEqualTo(MyTemplateEngineCustomizer.class);
    }

    @Test
    void testCustomFreeMarkerConfigUsingConfigurationProperty() {
        TestPropertyValues.of("mybatis.scripting-language-driver.freemarker.base-package=sqls",
                "mybatis.scripting-language-driver.freemarker.freemarker-settings.interpolation_syntax=dollar",
                "mybatis.scripting-language-driver.freemarker.freemarker-settings.whitespace_stripping=yes")
                .applyTo(this.context);
        this.context.register(MyAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class);
        this.context.refresh();
        FreeMarkerLanguageDriver driver = this.context.getBean(FreeMarkerLanguageDriver.class);
        @SuppressWarnings("unused")
        class Param {
            private Integer id;
            private Integer version;
        }
        Param params = new Param();
        params.id = 10;
        params.version = 20;
        SqlSource sqlSource = driver.createSqlSource(new Configuration(),
                "SELECT * FROM users WHERE id = #{id} and version = <@p name='version'/>", Param.class);
        BoundSql boundSql = sqlSource.getBoundSql(params);
        assertThat(boundSql.getSql()).isEqualTo("SELECT * FROM users WHERE id = ? and version = ?");
        assertThat(boundSql.getParameterMappings().get(0).getProperty()).isEqualTo("id");
        assertThat(boundSql.getParameterMappings().get(0).getJavaType()).isEqualTo(Integer.class);
        assertThat(boundSql.getParameterMappings().get(1).getProperty()).isEqualTo("version");
        assertThat(boundSql.getParameterMappings().get(1).getJavaType()).isEqualTo(Integer.class);
        FreeMarkerLanguageDriverConfig config = this.context.getBean(FreeMarkerLanguageDriverConfig.class);
        assertThat(config.getBasePackage()).isEqualTo("sqls");
        assertThat(config.getFreemarkerSettings()).hasSize(2);
        assertThat(config.getFreemarkerSettings().get("interpolation_syntax")).isEqualTo("dollar");
        assertThat(config.getFreemarkerSettings().get("whitespace_stripping")).isEqualTo("yes");
    }

    @Test
    void testCustomVelocityConfigUsingConfigurationProperty() {
        TestPropertyValues.of(
                "mybatis.scripting-language-driver.velocity.userdirective=" + NowDirective.class.getName(),
                "mybatis.scripting-language-driver.velocity.velocity-settings." + RuntimeConstants.INPUT_ENCODING
                        + "=" + RuntimeConstants.ENCODING_DEFAULT,
                "mybatis.scripting-language-driver.velocity.additional-context-attributes.attribute1=java.lang.String",
                "mybatis.scripting-language-driver.velocity.additional-context-attributes.attribute2=java.util.HashMap")
                .applyTo(this.context);
        this.context.register(MyAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class);
        this.context.refresh();
        VelocityLanguageDriver driver = this.context.getBean(VelocityLanguageDriver.class);
        @SuppressWarnings("unused")
        class Param {
            private Integer id;
            private Integer version;
        }
        Param params = new Param();
        params.id = 10;
        params.version = 20;
        SqlSource sqlSource = driver.createSqlSource(new Configuration(), "#now()", Param.class);
        BoundSql boundSql = sqlSource.getBoundSql(params);
        assertThat(boundSql.getSql()).isEqualTo("SELECT CURRENT_TIMESTAMP");
        VelocityLanguageDriverConfig config = this.context.getBean(VelocityLanguageDriverConfig.class);
        @SuppressWarnings("deprecation")
        String[] userDirective = config.getUserdirective();
        assertThat(userDirective).hasSize(1).contains(NowDirective.class.getName());
        assertThat(config.getAdditionalContextAttributes()).hasSize(2);
        assertThat(config.getAdditionalContextAttributes().get("attribute1")).isEqualTo("java.lang.String");
        assertThat(config.getAdditionalContextAttributes().get("attribute2")).isEqualTo("java.util.HashMap");
        assertThat(config.getVelocitySettings()).hasSize(3);
        assertThat(config.getVelocitySettings().get(RuntimeConstants.RESOURCE_LOADERS)).isEqualTo("class");
        assertThat(config.getVelocitySettings().get(RuntimeConstants.RESOURCE_LOADER + ".class.class"))
                .isEqualTo("org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        assertThat(config.generateCustomDirectivesString()).isEqualTo(NowDirective.class.getName()
                + ",org.mybatis.scripting.velocity.TrimDirective,org.mybatis.scripting.velocity.WhereDirective,org.mybatis.scripting.velocity.SetDirective,org.mybatis.scripting.velocity.InDirective,org.mybatis.scripting.velocity.RepeatDirective");
        assertThat(config.getVelocitySettings().get(RuntimeConstants.INPUT_ENCODING))
                .isEqualTo(RuntimeConstants.ENCODING_DEFAULT);

    }

    @Test
    void testExcludeMybatisLanguageDriverAutoConfiguration() {
        TestPropertyValues.of(
                "spring.autoconfigure.exclude:org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration")
                .applyTo(this.context);
        this.context.register(MyAutoConfiguration.class);
        this.context.refresh();
        assertThat(this.context.getBeanNamesForType(LanguageDriver.class)).hasSize(0);
    }

    @EnableAutoConfiguration
    private static class MyAutoConfiguration {
    }

    @org.springframework.context.annotation.Configuration
    static class TestingLegacyFreeMarkerConfiguration
            extends MybatisLanguageDriverAutoConfiguration.LegacyFreeMarkerConfiguration {
    }

    @org.springframework.context.annotation.Configuration
    static class TestingLegacyVelocityConfiguration
            extends MybatisLanguageDriverAutoConfiguration.LegacyVelocityConfiguration {
    }

    private static class MyLanguageDriverConfig {
        @Bean
        FreeMarkerLanguageDriver myFreeMarkerLanguageDriver() {
            return new FreeMarkerLanguageDriver();
        }

        @Bean
        VelocityLanguageDriver myVelocityLanguageDriver() {
            return new VelocityLanguageDriver();
        }

        @Bean
        ThymeleafLanguageDriver myThymeleafLanguageDriver() {
            return new ThymeleafLanguageDriver();
        }
    }

    private static class ThymeleafCustomLanguageDriverConfig {
        @Bean
        ThymeleafLanguageDriverConfig thymeleafLanguageDriverConfig() {
            return ThymeleafLanguageDriverConfig.newInstance(c -> c.getDialect().setPrefix("m"));
        }
    }

    private static class FreeMarkerCustomLanguageDriverConfig {
        @Bean
        FreeMarkerLanguageDriverConfig freeMarkerLanguageDriverConfig() {
            return FreeMarkerLanguageDriverConfig
                    .newInstance(c -> c.getFreemarkerSettings().put("interpolation_syntax", "dollar"));
        }
    }

    private static class VelocityCustomLanguageDriverConfig {
        @Bean
        VelocityLanguageDriverConfig velocityLanguageDriverConfig() {
            return VelocityLanguageDriverConfig.newInstance(c -> c.getVelocitySettings()
                    .put(RuntimeConstants.CUSTOM_DIRECTIVES, NowDirective.class.getName()));
        }
    }

    public static class MyTemplateEngineCustomizer implements TemplateEngineCustomizer {
        @Override
        public void customize(TemplateEngine defaultTemplateEngine) {
        }
    }

    public static class NowDirective extends Directive {

        @Override
        public String getName() {
            return "now";
        }

        @Override
        public int getType() {
            return LINE;
        }

        @Override
        public boolean render(InternalContextAdapter context, Writer writer, Node node)
                throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {
            writer.append("SELECT CURRENT_TIMESTAMP");
            return true;
        }

    }
}