| 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(@Nullable 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(@Nullable 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 |