1 | package com.reallifedeveloper.tools.test.database.dbunit; | |
2 | ||
3 | import java.io.IOException; | |
4 | import java.util.Arrays; | |
5 | import java.util.Optional; | |
6 | ||
7 | import javax.sql.DataSource; | |
8 | ||
9 | import org.checkerframework.checker.nullness.qual.Nullable; | |
10 | import org.dbunit.dataset.DataSetException; | |
11 | import org.dbunit.dataset.IDataSet; | |
12 | import org.dbunit.dataset.datatype.IDataTypeFactory; | |
13 | import org.dbunit.ext.mssql.InsertIdentityOperation; | |
14 | import org.dbunit.operation.DatabaseOperation; | |
15 | import org.junit.jupiter.api.AfterEach; | |
16 | import org.junit.jupiter.api.BeforeEach; | |
17 | import org.springframework.transaction.annotation.Transactional; | |
18 | ||
19 | /** | |
20 | * Base class for DBUnit tests. | |
21 | * <p> | |
22 | * An example of how to use this class: | |
23 | * | |
24 | * <pre> | |
25 | * @ExtendWith(SpringExtension.class) | |
26 | * @ContextConfiguration(classes = TestConfiguration.class) | |
27 | * public class MyDbTest extends AbstractDbTest { | |
28 | * @Autowired | |
29 | * private DataSource ds; | |
30 | * | |
31 | * @Autowired | |
32 | * private IDataTypeFactory dataTypeFactory; | |
33 | * | |
34 | * public MyDbTest() { | |
35 | * super(null, "/dbunit/myschema.dtd", "/dbunit/dataset1.xml", "/dbunit/dataset2.xml"); | |
36 | * } | |
37 | * | |
38 | * @Test | |
39 | * public void myTest() { | |
40 | * ... | |
41 | * } | |
42 | * | |
43 | * @Override | |
44 | * protected DataSource getDataSource() { return ds; } | |
45 | * | |
46 | * @Override | |
47 | * protected IDataTypeFactory getDataTypeFactory() { return dataTypeFactory; } | |
48 | * } | |
49 | * </pre> | |
50 | * | |
51 | * @author RealLifeDeveloper | |
52 | * | |
53 | */ | |
54 | @Transactional | |
55 | public abstract class AbstractDbTest { | |
56 | ||
57 | /** | |
58 | * The default operation to perform before executing each test. | |
59 | */ | |
60 | public static final DatabaseOperation DEFAULT_SETUP_OPERATION = InsertIdentityOperation.CLEAN_INSERT; | |
61 | ||
62 | /** | |
63 | * The default operation to perform after executing each test. | |
64 | */ | |
65 | public static final DatabaseOperation DEFAULT_TEARDOWN_OPERATION = DatabaseOperation.NONE; | |
66 | ||
67 | private Optional<String> schemaName; | |
68 | private Optional<String> dataSetDtdResourceName; | |
69 | private String[] dataSetResourceNames; | |
70 | ||
71 | private DbTestHelper dbTestHelper; | |
72 | ||
73 | /** | |
74 | * Creates a new test instance, using the given schema and reading the DBUnit XML file found in the given classpath resource. | |
75 | * | |
76 | * @param schemaName name of the database schema, or {@code null} | |
77 | * @param dataSetResourceName name of the classpath resource that contains DBUnit XML | |
78 | */ | |
79 | protected AbstractDbTest(String schemaName, String dataSetResourceName) { | |
80 | this(schemaName, null, dataSetResourceName); | |
81 | } | |
82 | ||
83 | /** | |
84 | * Creates a new test instance, using the given schema and reading the DBUnit XML files and DTD found in the given classpath resources. | |
85 | * | |
86 | * @param schemaName name of the database schema, or {@code null} | |
87 | * @param dataSetDtdResourceName name of the classpath resource containing the DTD for the XML, or {@code null} to not validate | |
88 | * @param dataSetResourceNames names of classpath resources containing DBUnit XML | |
89 | */ | |
90 | protected AbstractDbTest(String schemaName, @Nullable String dataSetDtdResourceName, String... dataSetResourceNames) { | |
91 |
1
1. <init> : negated conditional → KILLED |
if (dataSetResourceNames == null) { |
92 | throw new IllegalArgumentException("dataSetResourceName must not be null"); | |
93 | } | |
94 | this.schemaName = Optional.ofNullable(schemaName); | |
95 | this.dataSetDtdResourceName = Optional.ofNullable(dataSetDtdResourceName); | |
96 | this.dataSetResourceNames = dataSetResourceNames.clone(); | |
97 | } | |
98 | ||
99 | /** | |
100 | * Called before each test case to insert test data into the database. | |
101 | * | |
102 | * @throws Exception if something goes wrong | |
103 | */ | |
104 | @BeforeEach | |
105 | @SuppressWarnings("PMD.SignatureDeclareThrowsException") | |
106 | public void setUpDatabase() throws Exception { | |
107 | dbTestHelper = new DbTestHelper(getDataSource(), getDataSet(), getSchemaName(), getDataTypeFactory()); | |
108 |
1
1. setUpDatabase : removed call to com/reallifedeveloper/tools/test/database/dbunit/DbTestHelper::setSetUpOperation → SURVIVED |
dbTestHelper.setSetUpOperation(getSetUpOperation()); |
109 |
1
1. setUpDatabase : removed call to com/reallifedeveloper/tools/test/database/dbunit/DbTestHelper::setTearDownOperation → SURVIVED |
dbTestHelper.setTearDownOperation(getTearDownOperation()); |
110 |
1
1. setUpDatabase : removed call to com/reallifedeveloper/tools/test/database/dbunit/DbTestHelper::init → SURVIVED |
dbTestHelper.init(); |
111 | } | |
112 | ||
113 | /** | |
114 | * Called after each test case to clean the database from test data. | |
115 | * | |
116 | * @throws Exception if something goes wrong | |
117 | */ | |
118 | @AfterEach | |
119 | @SuppressWarnings("PMD.SignatureDeclareThrowsException") | |
120 | public void tearDownDatabase() throws Exception { | |
121 |
1
1. tearDownDatabase : negated conditional → KILLED |
if (dbTestHelper != null) { |
122 |
1
1. tearDownDatabase : removed call to com/reallifedeveloper/tools/test/database/dbunit/DbTestHelper::clean → SURVIVED |
dbTestHelper.clean(); |
123 | } | |
124 | } | |
125 | ||
126 | /** | |
127 | * Gives the name of the database schema. Can be {@code null}. | |
128 | * | |
129 | * @return the database schema name | |
130 | */ | |
131 | protected Optional<String> getSchemaName() { | |
132 |
1
1. getSchemaName : replaced return value with Optional.empty for com/reallifedeveloper/tools/test/database/dbunit/AbstractDbTest::getSchemaName → RUN_ERROR |
return schemaName; |
133 | } | |
134 | ||
135 | /** | |
136 | * Gives the name of the resource containing the DTD for test data files. | |
137 | * | |
138 | * @return the name of the DTD resource | |
139 | */ | |
140 | protected Optional<String> getDataSetDtdResourceName() { | |
141 |
1
1. getDataSetDtdResourceName : replaced return value with Optional.empty for com/reallifedeveloper/tools/test/database/dbunit/AbstractDbTest::getDataSetDtdResourceName → KILLED |
return dataSetDtdResourceName; |
142 | } | |
143 | ||
144 | /** | |
145 | * Gives the names of the resources containing test data. | |
146 | * | |
147 | * @return the names of the test data resources | |
148 | */ | |
149 | protected String[] getDataSetResourceNames() { | |
150 |
1
1. getDataSetResourceNames : replaced return value with null for com/reallifedeveloper/tools/test/database/dbunit/AbstractDbTest::getDataSetResourceNames → KILLED |
return Arrays.copyOf(dataSetResourceNames, dataSetResourceNames.length); |
151 | } | |
152 | ||
153 | /** | |
154 | * Gives the data set used by DbUnit when testing. The default implementation reads XML files from the classpath resources pointed to by | |
155 | * the {@code dataSetResourceNames} property, validating using the DTD pointed to by the {@code dataSetDtdResourceName} property. | |
156 | * <p> | |
157 | * Override this method if you want to provide the DbUnit test data in some other way. | |
158 | * | |
159 | * @return the test data set | |
160 | * | |
161 | * @throws DataSetException if some resource if malformed | |
162 | * @throws IOException if reading a resource failed | |
163 | */ | |
164 | protected IDataSet getDataSet() throws DataSetException, IOException { | |
165 | String dtdResourceName = getDataSetDtdResourceName().orElse(null); | |
166 |
1
1. getDataSet : replaced return value with null for com/reallifedeveloper/tools/test/database/dbunit/AbstractDbTest::getDataSet → KILLED |
return DbTestHelper.readDataSetFromClasspath(dtdResourceName, getDataSetResourceNames()); |
167 | } | |
168 | ||
169 | /** | |
170 | * Override this to point to your datasource. The datasource could, e.g., be injected by Spring. | |
171 | * | |
172 | * @return the {@code DataSource} to use | |
173 | */ | |
174 | protected abstract DataSource getDataSource(); | |
175 | ||
176 | /** | |
177 | * Gives the DbUnit {@code IDataTypeFactory} that matches the database used for testing, or {@code null} if the database type is left | |
178 | * unspecified. If left unspecified, DbUnit will probably issue a lot of warnings about "potential problems". | |
179 | * <p> | |
180 | * The default implementation returns {@code null}. Override this to return the right {@code IDataTypeFactory} for your database, e.g., | |
181 | * {@code org.dbunit.ext.mysql.MySqlDataTypeFactory} or {@code org.dbunit.ext.oracle.Oracle10DataTypeFactory}. | |
182 | * <p> | |
183 | * To make it easy to change to use a different database, the factory could be configured by Spring and injected into your test case. | |
184 | * | |
185 | * @return the{@code IDataTypeFactory} to use | |
186 | */ | |
187 | protected Optional<IDataTypeFactory> getDataTypeFactory() { | |
188 | return Optional.empty(); | |
189 | } | |
190 | ||
191 | /** | |
192 | * Gives the operation to perform before executing each test. | |
193 | * <p> | |
194 | * The default is {@link #DEFAULT_SETUP_OPERATION}. Override this method to change this behavior. | |
195 | * | |
196 | * @return the setup operation to perform | |
197 | */ | |
198 | protected DatabaseOperation getSetUpOperation() { | |
199 |
1
1. getSetUpOperation : replaced return value with null for com/reallifedeveloper/tools/test/database/dbunit/AbstractDbTest::getSetUpOperation → KILLED |
return DEFAULT_SETUP_OPERATION; |
200 | } | |
201 | ||
202 | /** | |
203 | * Gives the operation to perform after executing each test. | |
204 | * <p> | |
205 | * The default is {@link #DEFAULT_TEARDOWN_OPERATION}. Override this method to change this behavior. | |
206 | * | |
207 | * @return the setup operation to perform | |
208 | */ | |
209 | protected DatabaseOperation getTearDownOperation() { | |
210 |
1
1. getTearDownOperation : replaced return value with null for com/reallifedeveloper/tools/test/database/dbunit/AbstractDbTest::getTearDownOperation → KILLED |
return DEFAULT_TEARDOWN_OPERATION; |
211 | } | |
212 | ||
213 | /** | |
214 | * Make finalize method final to avoid "Finalizer attacks" and corresponding SpotBugs warning (CT_CONSTRUCTOR_THROW). | |
215 | * | |
216 | * @see <a href="https://wiki.sei.cmu.edu/confluence/display/java/OBJ11-J.+Be+wary+of+letting+constructors+throw+exceptions"> | |
217 | * Explanation of finalizer attack</a> | |
218 | */ | |
219 | @Override | |
220 | @SuppressWarnings({ "deprecation", "removal", "Finalize", "checkstyle:NoFinalizer", "PMD.EmptyFinalizer", | |
221 | "PMD.EmptyMethodInAbstractClassShouldBeAbstract" }) | |
222 | protected final void finalize() throws Throwable { | |
223 | // Do nothing | |
224 | } | |
225 | ||
226 | } | |
Mutations | ||
91 |
1.1 |
|
108 |
1.1 |
|
109 |
1.1 |
|
110 |
1.1 |
|
121 |
1.1 |
|
122 |
1.1 |
|
132 |
1.1 |
|
141 |
1.1 |
|
150 |
1.1 |
|
166 |
1.1 |
|
199 |
1.1 |
|
210 |
1.1 |