Use dbunit to test your Spring Boot project.
column | Mold | Primary key |
---|---|---|
person_id | integer | 〇 |
person_name | character varying(20) | |
birth_date | date | |
birth_place | character varying(20) |
I created the following Mapper with MyBatis for the table.
@Mapper
public interface PersonMapper {
@Select("SELECT * FROM person WHERE person_id = #{personId}")
public Person selectById(int personId);
@Insert("INSERT INTO person(person_id, person_name, birth_date, birth_place) VALUES (#{person_id}, #{person_name}, #{birth_date}, #{birth_place})")
public void insert(Person person);
}
Add spring-test-dbunit
and dbunit
to the dependencies.
pom.xml
<dependency>
<groupId>com.github.springtestdbunit</groupId>
<artifactId>spring-test-dbunit</artifactId>
<version>1.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.dbunit</groupId>
<artifactId>dbunit</artifactId>
<version>2.6.0</version>
<scope>test</scope>
</dependency>
Describe the data in the DB before executing the test (before executing the test method).
__ * In the following cases, the data used for the test will be committed __ (The rollback case will be described later)
dataset
tag and describe the data value to input the column name to the attribute value in the attribute name.Pattern A.xml
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<person person_id="1" person_name="Suzaki" birth_date="1986-12-25" />
<person person_id="2" person_name="Nishi" birth_place="Hyogo prefecture" />
<person person_id="3" birth_date="1994-02-22" birth_place="Tokyo" />
</dataset>
// (1)
@RunWith(SpringRunner.class)
@SpringBootTest
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class
})
public class PersonMapperTest {
@Autowired // (2)
PersonMapper mapper;
@Test
@DatabaseSetup("/dbunit/Pattern A.xml") // (3)
public void test() {
//Write test code
}
}
(1) | Write all the above annotations in the test class |
(2) | Autowired is possible to start Spring |
(3) | In the test method@DatabaseSetup And describe the xml path in its argument |
# SELECT * FROM person;
person_id | person_name | birth_date | birth_place
-----------+-------------+------------+-------------
1 | Suzaki | 1986-12-25 |
2 | Nishi | |Hyogo prefecture
3 | | 1994-02-22 |Tokyo
(3 lines)
If you write one line of tags without attributes as shown below, only DELETE will be executed and the table will be empty.
Pattern B.xml
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<person />
</dataset>
# SELECT * FROM person;
person_id | person_name | birth_date | birth_place
-----------+-------------+------------+-------------
(0 line)
Pattern C.xml
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<person person_id="4" person_name="" birth_date="1991-12-25" birth_place="Hyogo prefecture" />
</dataset>
If the above xml is read only with the basic pattern test code, the following exception will occur.
java.lang.IllegalArgumentException: table.column=person.person_name value is empty but must contain a value (to disable this feature check, set DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS to true)
Add the following configuration to the path read when running the test.
@Configuration
public class DatasourceConfig {
// (1)
@Bean
public DatabaseConfigBean dbUnitDatabaseConfig() {
DatabaseConfigBean bean = new DatabaseConfigBean();
bean.setAllowEmptyFields(true); // (2)
return bean;
}
// (3)
@Bean
public DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnection(
DatabaseConfigBean dbUnitDatabaseConfig,
DataSource dataSource
) {
DatabaseDataSourceConnectionFactoryBean bean = new DatabaseDataSourceConnectionFactoryBean(dataSource);
bean.setDatabaseConfig(dbUnitDatabaseConfig);
return bean;
}
}
(1) | Register the runtime config as a bean |
(2) | Turn on the switch that allows empty strings(The default is false) |
(3) | (1)Reflect the setting of to Datasource used in Spring |
# SELECT * FROM person;
person_id | person_name | birth_date | birth_place
-----------+-------------+------------+-------------
4 | | 1991-12-25 |Hyogo prefecture
(1 line)
@Test
@DatabaseSetup("/dbunit/Pattern C.xml")
public void test() {
Person actual = mapper.selectById(4);
assertThat(actual.getPerson_name()).isEqualTo(""); // ->success
}
Add listeners and annotations to the base pattern.
@RunWith(SpringRunner.class)
@SpringBootTest
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class, // (1)
DbUnitTestExecutionListener.class
})
@Transactional //(2)
public class PersonMapperTest3 {
...
}
(1) | Add a listener for transaction management |
(2) | A unit that actually manages transactions(Basically class)so@Transactional Grant |
You can also add @Transactional
to the method.
@Test
@Transactional
@DatabaseSetup("/dbunit/Pattern A.xml")
public void test() {
...
}
When executed with the above pattern, the following log is output at the WARN level.
Potential problem found: The configured data type factory 'class org.dbunit.dataset.datatype.DefaultDataTypeFactory' might cause problems with the current database 'PostgreSQL' (e.g. some datatypes may not be supported properly). In rare cases you might see this message because the list of supported database products is incomplete (list=[derby]). If so please request a java-class update via the forums.If you are using your own IDataTypeFactory extending DefaultDataTypeFactory, ensure that you override getValidDbProducts() to specify the supported database products.
Since the log says that DataTypeFactory is not specified, add the following description to the configuration class used in the empty string input pattern.
@Bean
public DatabaseConfigBean dbUnitDatabaseConfig() {
DatabaseConfigBean bean = new DatabaseConfigBean();
bean.setAllowEmptyFields(true);
bean.setDatatypeFactory(new PostgresqlDataTypeFactory()); // (1)
return bean;
}
(1) | Since PostgreSQL is used, the DataTypeFactory for PostgreSQL provided by dbunit is specified. |
Describe in the same format as the prerequisite data. When null or empty string is assumed, it is the same as the prerequisite data input.
Pattern D.xml
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<person person_id="1" person_name="Suzaki" birth_date="1986-12-25" />
<person person_id="2" person_name="Nishi" birth_place="Hyogo prefecture" />
<person person_id="3" birth_date="1994-02-22" birth_place="" />
</dataset>
Assumed result 1.xml
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<person person_id="1" person_name="Suzaki" birth_date="1986-12-25" />
<person person_id="2" person_name="Nishi" birth_place="Hyogo prefecture" />
<person person_id="3" birth_date="1994-02-22" birth_place="" />
<person person_id="11" person_name="Uesaka" birth_date="1991-12-19" birth_place="Kanagawa Prefecture" />
</dataset>
@Test
@DatabaseSetup("/dbunit/Pattern D.xml")
@ExpectedDatabase(
value="/dbunit/Assumed result 1.xml",
assertionMode=DatabaseAssertionMode.NON_STRICT
) // (1)
public void test() {
Person param = new Person();
param.setPerson_id(11);
param.setPerson_name("Uesaka");
param.setBirth_date(new Date(91, 11, 19));
param.setBirth_place("Kanagawa Prefecture");
mapper.insert(param);
}
(1) | Describe the annotation that specifies the expected result. By default all tables are checked, but assertionMode=NON_If STRICT is used, only the table described in xml will be inspected. |
SpringBoot 45.Testing Spring Framework Unit test implementation method 1-3. Repository test (Junit4, spring-test, DBUnit) │ ヰ Sword toy box How to set default properties in spring dataset DatabaseConfig - Stack Overflow
Recommended Posts