UTFlute- 0.4.0 0.4.6 をリリースしました
大きな変更点としては、
inject()メソッドの仕様を実際のDIコンテナに近づけました。
今まではかなりアバウトだったのですが、
「DIができるか」のテストに向かなかったので、
少し厳しめにしました。
ちなみに、テストケースクラス自体はDIは変わりません。
テストケースのクラスはアバウトの方がいいと思うので。
inject()メソッドにぶち込んだBeanに対するDIの話です。
って、そもそもUTFluteってなに?
ずばり!
「自分でnewしたものにDIできる JUnit 拡張」
です。
DBFlute の Example のテストケースで使っています。
幾つかの業務の現場でも導入しています。
jfluteがあんまりプロモーションをしていない、
「知る人ぞ知るツール」です。
今後もそんな感じです、きっと。
でも、身の回りでわりと使ってくれる人が
ちょっと増えてきたので、
(少しだけ)しっかり書いてみようと^^
FooAction action = new FooAction();
inject(action);
action.index();
FooAction自体をDIすると...
Interceptorが動いちゃってテストがしづらい。
でも、自分でnewすると...
DIされてないからほとんど動かない。
自分でセット、Mockをセットとか言っても量が多すぎるよぅ。
ということで、自分でnewしつつDIされたらいいなぁってね。
そういう発想から作られました。
そして、自分でnewするとうれしいこともうひとつ。
FooActionにMockしたい処理があったときに、
オーバーライドで簡単にMockできるというところ。
FooAction action = new FooAction() {
@Override
protected FooBean findStoredBean() {
return new FooBean(...);
}
};
inject(action);
action.index();
もちろん、世の中便利なMockツールはたくさんありますが、
Javaの文法を知っていれば使えるってのは、
それはそれで手軽だなぁと。
UnitTestって「いろいろ」と敷居が高いものです。
なのでまあ、こんな感じのアプローチもあっていいかなってね。
// 現場のテストコードはどこへ?
http://d.hatena.ne.jp/jflute/20120806/1344262853
さて、ここからは 0.4.0 から導入された
新機能を見ていきましょう!
markHere()
ここを通った!っていうマークを付けられます。
memberBhv.selectCursor(cb, entity -> {
... = entity.get...
markHere("called");
});
assertMarked("called");
まあ、よく boolean 宣言してtrueにしてassert、
とか、よく Set を宣言して add して...
みたいなことをやっていたのを気軽に実現できます。
markHere()の引数の文字列は任意のキー。
なので、一つのテストケースで複数同時に利用できます。
JUnitは素通りするとGreenになってしまいますから、
assertしたこと自体を保証するためにも使えるかと。
for (Member member : memberList) {
if (member.isMemberStatusCodeFormalized()) {
assertTrue(member...);
assertMarked("exists");
}
...
}
assertMarked("exists");
また、
「markしておきながらassertし忘れたー(><」
ってとき、
テストの終了時に例外になって教えてくれます。
memberBhv.selectCursor(cb, entity -> {
... = entity.get...
markHere("called");
});
(デフォルトで)10個のスレッドを、
「いっせーのーせっ!」
で同時に実行させてマルチスレッドのテストができます。
cannonball(car -> {
car.goal(memberList);
}, new CannonballOption().expectSameResult());
同じ結果であることのassertや、
例外が発生することのassertなど、
CannonballOptionでいろいろと用意されています。
もちろん、自分で適宜 assert を入れちゃってOK。
とにかく、気軽にマルチスレッドの「よーいどん!」
ができるのはいざってときにとても助かります。
っていっても、
業務のUnitTestではあんまり役に立たないかな...!?
まあ、DBFluteではめっちゃ使っています。
スレッドセーフであることを検証する必要があるので。
ライブラリ的なクラスのテストに向いてるんじゃないかと。
複数のスレッドに「順番に」処理をさせていくこともできます。
実際に、DBFluteのDBMSのLock待ちのテストで利用しています。
cannonball(car -> {
car.projectA(dragon -> {
Member member = new Member();
member.setMemberId(memberId);
member.setMemberName("lock1");
memberBhv.updateNonstrict(member);
}, 1);
car.projectA(dragon ->
dragon.expectOvertime();
Purchase purchase = new Purchase();
purchase.setMemberId(memberId);
purchase.setProductId(1);
purchase.setPurchaseDatetime(currentTimestamp());
purchase.set...
purchaseBhv.insert(purchase);
}, 2);
}, new CannonballOption().threadCount(2));
policeStoryOf...()
いろいろなものを chase できます。
例えば、src/main/java配下のJavaクラスを走査して、
アノテーションとか宣言のチェックとか...
policeStoryOfJavaClassChase((srcFile, clazz) -> {
... = clazz.getMethods();
});
さっそく現場でやっているのが...
SeasarのスマートデプロイのクラスのDIって、
インスタンス変数の名前でDIするのですが、
名前が間違ってるとDIされません。
@Resource
protected MemberLogic memberFlute;
例えば、
「先頭小文字にしたLogicクラス名 = 変数名」
であることをassertするテストケースを書いてみました。
まあ、もちろん画面起動でも既に動かないですけど、
HotDeployだとその画面に行かないとエラーにならないし、
とにもかくにもリファクタリングしたときとかに、
一括でチェックできるってのは安心感あります。
というか、これはほんの入り口、
もっと色々な独自のチェックができるかなと。
CheckStyleとかではなかなか届かない、
業務的な習慣のチェックとかに活用できればと。
※JSPファイルとかも走査できるので、まあいろいろと...^^
さいごに
Google Guice 対応もしました。
あと、HttpServlet の Mock も導入しました。
Maven の artifactId に指定できるものは:
o utflute-seasar -> Seasarを使ってるなら
o utflute-spring -> SpringでWeb要らないなら
o utflute-guice -> GuiceでWeb要らないなら
o utflute-spring-web -> SpringでWebが要るなら
o utflute-guice-web ->: GuiceでWebが要るなら
<dependency>
<groupId>org.seasar.dbflute</groupId>
<artifactId>utflute-seasar</artifactId>
<version>0.4.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seasar.dbflute</groupId>
<artifactId>utflute-spring-web</artifactId>
<version>0.4.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seasar.dbflute</groupId>
<artifactId>utflute-guice-web</artifactId>
<version>0.4.6</version>
<scope>test</scope>
</dependency>
サンプルコード、Java8スタイルで書いちゃいました^^。
その方が、ブログとかに書くとき楽なんですもの。
Java8リリースおめでとう!
(まだ Java8 ぜんぜんさわってないけど。。。)
#
# 【追記】
# 取り急ぎ、UTFluteのオフィシャルページを作りました。
# 環境構築のやり方が載っています。
# -> UTFlute | DBFlute
#