Spring BootにおけるRepository層に対する単体テスト
目次
ソース
AddressMapper.java
@Select("SELECT * FROM address WHERE city_id = #{cityId}")
Set<Address> findAddress(@Param("cityId") int cityId);
複数のデータが返ってくるようなSQLです。
AddressMapperTests.java
@MybatisTest
public class AddressMapperTests {
@Autowired
private AddressMapper target;
@Autowired
private DataSource dataSource;
private final Operation RESET_DATA = Operations.deleteAllFrom("address");
private void dbSetup(Operation operation) {
Destination destination = new DataSourceDestination(dataSource);
DbSetup dbSetup = new DbSetup(destination, operation);
dbSetup.launch();
}
@BeforeEach
void setUp() {
dbSetup(Operations.sequenceOf(
RESET_DATA
));
}
@AfterEach
void tearDown() {
dbSetup(Operations.sequenceOf(
RESET_DATA
));
}
@DisplayName("データ検証テスト")
@Nested
class FieldValue {
private final Operation INSERT_ADDRESS_DATA = Operations.insertInto("address")
.columns("address_id", "address", "district", "city_id", "phone", "last_update")
.values(1, "fashion 109", "Shibuya", 1, "28303384290", "2012-01-01 12:12:00")
.values(2, "salary 999", "Shinbashi", 1, "635297277345", "2012-01-02 12:12:00")
.build();
@BeforeEach
void setUp() {
dbSetup(INSERT_ADDRESS_DATA);
}
@DisplayName("Setに含まれる要素をまとめて検証する")
@Test
void dataValueTest() {
//GIVEN
int cityId = 1;
//WHEN
Set<Address> actual = target.findAddress(cityId);
//THEN
assertThat(actual).extracting("addressId").allMatch(i -> Arrays.asList(1, 2).contains(i));
assertThat(actual).extracting("address").allMatch(i -> Arrays.asList("fashion 109", "salary 999").contains(i));
assertThat(actual).extracting("address2").allMatch(Objects::isNull);
assertThat(actual).extracting("district").allMatch(i -> Arrays.asList("Shibuya", "Shinbashi").contains(i));
assertThat(actual).extracting("postalCode").allMatch(Objects::isNull);
assertThat(actual).extracting("phone").allMatch(i -> Arrays.asList("28303384290", "635297277345").contains(i));
assertThat(actual).extracting("lastUpdate").allMatch(i -> Arrays.asList(
LocalDateTime.parse("2012-01-01 12:12:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
LocalDateTime.parse("2012-01-02 12:12:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
).contains(i));
}
}
}
解説
解説したいところは2点あります。
@MybatisTest
@MybatisTestを使用することで、MybatisによるSQL実行に必要なコンポーネントのみを読み込んでくれるので、リソースが必要最小限で済みます。
@SpringBootTestでも動くのですが、@SpringBootTestの場合はプロジェクトのコンポーネント全てを読み込んでしまうので、Testに時間がかかります。
Collection型のオブジェクトの中身をまとめて検証する
THENで検証しているところで、Set型のオブジェクトの中身をまとめて検証しています。
List型では順番にfor文でオブジェクトを取り出して値を一つ一つ検証するということも可能ですが、Set型は順序性が担保されていないため、一つ一つ取り出して検証ということが出来ません。
そういった時に「それぞれのオブジェクトの中にどんな値が入っていればOKなのか」を示してあげて、一致すればOKという感じでテストしています。
「それぞれのオブジェクトの中にどんな値が入っていればOKなのか」
assertThat(actual).extracting("phone").allMatch(i -> Arrays.asList("28303384290", "635297277345").contains(i));
「それぞれのオブジェクトの中に何も入ってなければOK」
assertThat(actual).extracting("address2").allMatch(Objects::isNull);