View Javadoc
1   /*
2    *    Copyright 2009-2025 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    *       https://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.mybatis.guice;
17  
18  import static java.lang.System.currentTimeMillis;
19  
20  import static com.google.inject.Guice.createInjector;
21  import static com.google.inject.name.Names.bindProperties;
22  import static com.google.inject.name.Names.named;
23  
24  import com.google.inject.Binder;
25  import com.google.inject.Injector;
26  import com.google.inject.Module;
27  
28  import java.io.StringReader;
29  import java.sql.SQLException;
30  import java.util.List;
31  import java.util.Properties;
32  
33  import javax.sql.DataSource;
34  
35  import org.apache.ibatis.jdbc.ScriptRunner;
36  import org.apache.ibatis.mapping.Environment;
37  import org.apache.ibatis.session.SqlSessionFactory;
38  import org.junit.jupiter.api.extension.AfterEachCallback;
39  import org.junit.jupiter.api.extension.BeforeEachCallback;
40  import org.junit.jupiter.api.extension.ExtensionContext;
41  import org.junit.jupiter.api.extension.TestInstanceFactory;
42  import org.junit.jupiter.api.extension.TestInstanceFactoryContext;
43  import org.junit.jupiter.api.extension.TestInstantiationException;
44  
45  abstract class AbstractGuiceTestExtension implements AfterEachCallback, BeforeEachCallback, TestInstanceFactory {
46  
47    private final Injector injector;
48  
49    public AbstractGuiceTestExtension() throws SQLException {
50      final Contact contact = new Contact();
51      contact.setFirstName("John");
52      contact.setLastName("Doe");
53      contact.setCreated(new CustomType(currentTimeMillis()));
54      contact.setAddress(null);
55  
56      final Contact contactWithAddress = new Contact();
57      contactWithAddress.setFirstName("John");
58      contactWithAddress.setLastName("Doe");
59      contactWithAddress.setCreated(new CustomType(currentTimeMillis()));
60  
61      final Address address = new Address();
62      address.setNumber(1234);
63      address.setStreet("Elm street");
64      contactWithAddress.setAddress(address);
65  
66      final Counter counter = new Counter();
67  
68      // bindings
69      final List<Module> modules = this.createMyBatisModule();
70      modules.add(new Module() {
71        @Override
72        public void configure(Binder binder) {
73          bindProperties(binder, createTestProperties());
74          binder.bind(Contact.class).toInstance(contact);
75          binder.bind(Contact.class).annotatedWith(named("contactWithAddress")).toInstance(contactWithAddress);
76          binder.bind(Counter.class).toInstance(counter);
77        }
78      });
79      this.injector = createInjector(modules);
80  
81      // prepare the test db
82      final Environment environment = this.injector.getInstance(SqlSessionFactory.class).getConfiguration()
83          .getEnvironment();
84      final DataSource dataSource = environment.getDataSource();
85      final ScriptRunner runner = new ScriptRunner(dataSource.getConnection());
86      runner.setAutoCommit(true);
87      runner.setStopOnError(true);
88      runner.runScript(new StringReader("DROP TABLE IF EXISTS contact;"
89          + "CREATE TABLE contact (id int GENERATED BY DEFAULT AS IDENTITY (START WITH 1), "
90          + "first_name VARCHAR(20) NOT NULL, " + "last_name VARCHAR(20) NOT NULL, " + "created TIMESTAMP, "
91          + "address VARCHAR(100) DEFAULT NULL) ;"));
92      dataSource.getConnection().close();
93    }
94  
95    protected abstract List<Module> createMyBatisModule();
96  
97    protected abstract Properties createTestProperties();
98  
99    @Override
100   public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext)
101       throws TestInstantiationException {
102     return this.injector.getInstance(factoryContext.getTestClass());
103   }
104 
105   @Override
106   public void afterEach(ExtensionContext context) throws Exception {
107     CleanDatabaseRule extension = injector.getInstance(CleanDatabaseRule.class);
108     extension.evaluate();
109   }
110 
111   @Override
112   public void beforeEach(ExtensionContext context) throws Exception {
113     CleanDatabaseRule extension = injector.getInstance(CleanDatabaseRule.class);
114     extension.evaluate();
115   }
116 
117 }