View Javadoc
1   /*
2    *    Copyright 2009-2021 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.apache.ibatis.builder;
17  
18  import static com.googlecode.catchexception.apis.BDDCatchException.*;
19  import static org.assertj.core.api.Assertions.assertThat;
20  import static org.assertj.core.api.BDDAssertions.then;
21  
22  import java.io.InputStream;
23  import java.util.regex.Pattern;
24  
25  import org.apache.ibatis.builder.xml.XMLMapperBuilder;
26  import org.apache.ibatis.io.Resources;
27  import org.apache.ibatis.mapping.MappedStatement;
28  import org.apache.ibatis.mapping.ResultSetType;
29  import org.apache.ibatis.mapping.StatementType;
30  import org.apache.ibatis.session.Configuration;
31  import org.apache.ibatis.type.TypeHandler;
32  import org.junit.jupiter.api.Assertions;
33  import org.junit.jupiter.api.Test;
34  
35  class XmlMapperBuilderTest {
36  
37    @Test
38    void shouldSuccessfullyLoadXMLMapperFile() throws Exception {
39      Configuration configuration = new Configuration();
40      String resource = "org/apache/ibatis/builder/AuthorMapper.xml";
41      try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
42        XMLMapperBuilder builder = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
43        builder.parse();
44      }
45    }
46  
47    @Test
48    void mappedStatementWithOptions() throws Exception {
49      Configuration configuration = new Configuration();
50      String resource = "org/apache/ibatis/builder/AuthorMapper.xml";
51      try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
52        XMLMapperBuilder builder = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
53        builder.parse();
54  
55        MappedStatement mappedStatement = configuration.getMappedStatement("selectWithOptions");
56        assertThat(mappedStatement.getFetchSize()).isEqualTo(200);
57        assertThat(mappedStatement.getTimeout()).isEqualTo(10);
58        assertThat(mappedStatement.getStatementType()).isEqualTo(StatementType.PREPARED);
59        assertThat(mappedStatement.getResultSetType()).isEqualTo(ResultSetType.SCROLL_SENSITIVE);
60        assertThat(mappedStatement.isFlushCacheRequired()).isFalse();
61        assertThat(mappedStatement.isUseCache()).isFalse();
62      }
63    }
64  
65    @Test
66    void mappedStatementWithoutOptionsWhenSpecifyDefaultValue() throws Exception {
67      Configuration configuration = new Configuration();
68      configuration.setDefaultResultSetType(ResultSetType.SCROLL_INSENSITIVE);
69      String resource = "org/apache/ibatis/builder/AuthorMapper.xml";
70      InputStream inputStream = Resources.getResourceAsStream(resource);
71      XMLMapperBuilder builder = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
72      builder.parse();
73      inputStream.close();
74  
75      MappedStatement mappedStatement = configuration.getMappedStatement("selectAuthor");
76      assertThat(mappedStatement.getResultSetType()).isEqualTo(ResultSetType.SCROLL_INSENSITIVE);
77    }
78  
79    @Test
80    void parseExpression() {
81      BaseBuilder builder = new BaseBuilder(new Configuration()){{}};
82      {
83        Pattern pattern = builder.parseExpression("[0-9]", "[a-z]");
84        assertThat(pattern.matcher("0").find()).isTrue();
85        assertThat(pattern.matcher("a").find()).isFalse();
86      }
87      {
88        Pattern pattern = builder.parseExpression(null, "[a-z]");
89        assertThat(pattern.matcher("0").find()).isFalse();
90        assertThat(pattern.matcher("a").find()).isTrue();
91      }
92    }
93  
94    @Test
95    void resolveJdbcTypeWithUndefinedValue() {
96      BaseBuilder builder = new BaseBuilder(new Configuration()){{}};
97      when(() -> builder.resolveJdbcType("aaa"));
98      then(caughtException())
99        .isInstanceOf(BuilderException.class)
100       .hasMessageStartingWith("Error resolving JdbcType. Cause: java.lang.IllegalArgumentException: No enum")
101       .hasMessageEndingWith("org.apache.ibatis.type.JdbcType.aaa");
102   }
103 
104   @Test
105   void resolveResultSetTypeWithUndefinedValue() {
106     BaseBuilder builder = new BaseBuilder(new Configuration()){{}};
107     when(() -> builder.resolveResultSetType("bbb"));
108     then(caughtException())
109       .isInstanceOf(BuilderException.class)
110       .hasMessageStartingWith("Error resolving ResultSetType. Cause: java.lang.IllegalArgumentException: No enum")
111       .hasMessageEndingWith("org.apache.ibatis.mapping.ResultSetType.bbb");
112   }
113 
114   @Test
115   void resolveParameterModeWithUndefinedValue() {
116     BaseBuilder builder = new BaseBuilder(new Configuration()){{}};
117     when(() -> builder.resolveParameterMode("ccc"));
118     then(caughtException())
119       .isInstanceOf(BuilderException.class)
120       .hasMessageStartingWith("Error resolving ParameterMode. Cause: java.lang.IllegalArgumentException: No enum")
121       .hasMessageEndingWith("org.apache.ibatis.mapping.ParameterMode.ccc");
122   }
123 
124   @Test
125   void createInstanceWithAbstractClass() {
126     BaseBuilder builder = new BaseBuilder(new Configuration()){{}};
127     when(() -> builder.createInstance("org.apache.ibatis.builder.BaseBuilder"));
128     then(caughtException())
129       .isInstanceOf(BuilderException.class)
130       .hasMessage("Error creating instance. Cause: java.lang.NoSuchMethodException: org.apache.ibatis.builder.BaseBuilder.<init>()");
131   }
132 
133   @Test
134   void resolveClassWithNotFound() {
135     BaseBuilder builder = new BaseBuilder(new Configuration()){{}};
136     when(() -> builder.resolveClass("ddd"));
137     then(caughtException())
138       .isInstanceOf(BuilderException.class)
139       .hasMessage("Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'ddd'.  Cause: java.lang.ClassNotFoundException: Cannot find class: ddd");
140   }
141 
142   @Test
143   void resolveTypeHandlerTypeHandlerAliasIsNull() {
144     BaseBuilder builder = new BaseBuilder(new Configuration()){{}};
145     TypeHandler<?> typeHandler = builder.resolveTypeHandler(String.class, (String)null);
146     assertThat(typeHandler).isNull();
147   }
148 
149   @Test
150   void resolveTypeHandlerNoAssignable() {
151     BaseBuilder builder = new BaseBuilder(new Configuration()){{}};
152     when(() -> builder.resolveTypeHandler(String.class, "integer"));
153     then(caughtException())
154       .isInstanceOf(BuilderException.class)
155       .hasMessage("Type java.lang.Integer is not a valid TypeHandler because it does not implement TypeHandler interface");
156   }
157 
158   @Test
159   void setCurrentNamespaceValueIsNull() {
160     MapperBuilderAssistant builder = new MapperBuilderAssistant(new Configuration(), "resource");
161     when(() -> builder.setCurrentNamespace(null));
162     then(caughtException())
163       .isInstanceOf(BuilderException.class)
164       .hasMessage("The mapper element requires a namespace attribute to be specified.");
165   }
166 
167   @Test
168   void useCacheRefNamespaceIsNull() {
169     MapperBuilderAssistant builder = new MapperBuilderAssistant(new Configuration(), "resource");
170     when(() -> builder.useCacheRef(null));
171     then(caughtException())
172       .isInstanceOf(BuilderException.class)
173       .hasMessage("cache-ref element requires a namespace attribute.");
174   }
175 
176   @Test
177   void useCacheRefNamespaceIsUndefined() {
178     MapperBuilderAssistant builder = new MapperBuilderAssistant(new Configuration(), "resource");
179     when(() -> builder.useCacheRef("eee"));
180     then(caughtException())
181       .hasMessage("No cache for namespace 'eee' could be found.");
182   }
183 
184   @Test
185   void shouldFailedLoadXMLMapperFile() throws Exception {
186     Configuration configuration = new Configuration();
187     String resource = "org/apache/ibatis/builder/ProblemMapper.xml";
188     try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
189       XMLMapperBuilder builder = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
190       Exception exception = Assertions.assertThrows(BuilderException.class, builder::parse);
191       Assertions.assertTrue(exception.getMessage().contains("Error parsing Mapper XML. The XML location is 'org/apache/ibatis/builder/ProblemMapper.xml'"));
192     }
193   }
194 
195 //  @Test
196 //  public void shouldNotLoadTheSameNamespaceFromTwoResourcesWithDifferentNames() throws Exception {
197 //    Configuration configuration = new Configuration();
198 //    String resource = "org/apache/ibatis/builder/AuthorMapper.xml";
199 //    InputStream inputStream = Resources.getResourceAsStream(resource);
200 //    XMLMapperBuilder builder = new XMLMapperBuilder(inputStream, configuration, "name1", configuration.getSqlFragments());
201 //    builder.parse();
202 //    InputStream inputStream2 = Resources.getResourceAsStream(resource);
203 //    XMLMapperBuilder builder2 = new XMLMapperBuilder(inputStream2, configuration, "name2", configuration.getSqlFragments());
204 //    builder2.parse();
205 //  }
206 
207    @Test
208    void errorResultMapLocation() throws Exception {
209      Configuration configuration = new Configuration();
210      String resource = "org/apache/ibatis/builder/ProblemResultMapper.xml";
211      try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
212        XMLMapperBuilder builder = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
213        builder.parse();
214        String resultMapName = "java.lang.String";
215        // namespace + "." + id
216        String statementId = "org.mybatis.spring.ErrorProblemMapper" + "." + "findProblemResultMapTest";
217        // same as MapperBuilderAssistant.getStatementResultMaps Exception message
218        String message = "Could not find result map '" + resultMapName + "' referenced from '" + statementId + "'";
219        IncompleteElementException exception = Assertions.assertThrows(IncompleteElementException.class,
220          ()-> configuration.getMappedStatement("findProblemTypeTest"));
221        assertThat(exception.getMessage()).isEqualTo(message);
222      }
223    }
224 }