SpringのUTにDBSetupを使ってみたら良かった
はじまり
DBのテスト、できればきれいに書きたい。
ということで
- insert文とかベタ書き : なんか嫌だ
- DBUnit : 使ったことはあるけど、ファイル参照嫌だ
- オレオレUtil : 再利用性がない!
ということで、DBSetupというのを見つけた。
データは「流れるようなインタフェース(Fluent Interface)」で作成する。
この一文に惚れたからだ。
自分の環境
- spring-boot
- JPARepository
- JUnit4
これに合うようにやってみた。
テストされる側
単にデータを全部返すだけのメソッド
@Service
@Transactional
public class MyDataService {
@Autowired
MyDataRepository myDataRepository;
public List<MyData> findAll() {
return myDataRepository.findAll(new Sort(Sort.Direction.ASC, "id"));
}
}
使ってみた
とりあえずversion2.0をimport
pom.xml
<!-- https://mvnrepository.com/artifact/com.ninja-squad/DbSetup -->
<dependency>
<groupId>com.ninja-squad</groupId>
<artifactId>DbSetup</artifactId>
<version>2.0.0</version>
</dependency>
SpringBootはテスト時はtest/resources/application.propertiesがあったらそちらを読み込むので作成。
spring.datasource.url=jdbc:mysql://192.168.33.10/mytestdatabase
spring.datasource.username=testuser
spring.datasource.password=password
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
これで通常環境は汚染されない。
DataSourceどうやってとってくるかで迷ったけど、普通に@Autowireで
DataSouce取ればテスト用のDataSouceが入ってた。
@RunWith(SpringRunner.class)
@SpringBootTest
この辺のDIのおかげかな。
あとは、データの定義、これがカッコイイ!!!
クラス内にデータがどうなっているか収まるのでDBUnitよりも読みやすい!!!
public static final Operation DELETE_ALL =
Operations.deleteAllFrom("mydata");
public static final Operation INSERT =
Operations.insertInto("mydata")
.columns("id", "name")
.values("1","Tanaka")
.values("2","Yoshida")
.values("3","Suzuki")
.build();
で、Beforeでデータをセットしてやると。
@Before
public void before(){
Destination dest = new DataSourceDestination(dataSource);
Operation ops = Operations.sequenceOf(DELETE_ALL, INSERT);
DbSetup dbSetup = new DbSetup(dest, ops);
dbSetup.launch();
}
sequenceOfで生成したOperationを繋げられるので楽!
あとは普通にテストすれば
@Autowired
MyDataService myDataService;
@Test
public void canFindAll() throws Exception {
List<MyData> myData = myDataService.findAll();
assertThat(myData.get(0).getId(),is(1));
assertThat(myData.get(0).getName(),is("Tanaka"));
}
オールグリーン!!!
まぁ、使ってみたかっただけのテストなんで、テスト自体は雑ですが。
なんて素敵なんだろう。この流れるようなインターフェース。
もうDBUnitのことなんて忘れよう!
DBのテストをこれで切り出して、
その部分がテストされていればあとはMockitoとかでMockすればいいし。
うん、なんか結局惚れた!