apimock 0.2.0 を出した
https://github.com/tokuhirom/apimock/
外部の API を呼ぶときにそのモックをつくるやつの 0.2.0 を出した。
外部の API を呼ぶようなコードを、呼び出し部分のクラスをモッキングしてもいいのだが、それよりも API サーバーそのものをモッキングしたほうが、より広い範囲のテストを同時に行うことができて良い。
というわけで、最近は Embedded Tomcat を使って実際にサーバーをたちあげてテストしている。 想像されるほど遅くはないのでよい。
基本的な使い方は以下のようになっており、mock#get と mock#post が用意されていて、ここにエンドポイントを登録してモッキングする。webscrew のレスポンス型以外のオブジェクトを返すと Jackson で適当に JSON にしてくれるので便利だ。
try (APIMockTomcat mock = new APIMockTomcat()) {
mock.get("/", c -> Collections.emptyMap());
mock.start();
URI uri = mock.getURI();
// Your test code here.
HttpResponse resp = Request.Get(uri.resolve("/"))
.execute()
.returnResponse();
assertEquals(200, resp.getStatusLine().getStatusCode());
assertEquals("{}", EntityUtils.toString(resp.getEntity()));
}
で、便利に使っていたのだが、今までは APIMockContext#readJSON のようなメソッドがなくて、出力はいいけど入力が辛い、ということになっていたので直した。
mock.get("/", c -> {
V v = c.readJSON(V.class);
return ImmutableMap.builder()
.put("x", v.getX()*2)
.build();
});
mock.start();
まあ、それだけですが。
最近の Web 開発は、外部 API との通信を行うケースが増えているので、こういうライブラリの需要が高まっていると思う今日このごろです(Perl でやってると fork しなきゃいけないのでちょっと管理が面倒だったけど Java だと thread なので楽でいい)。
ちなみに、実際にはこういうふうなのを毎回書くわけではなくて以下の様なヘルパメソッドを用意している。
protected void mockTwitter(Consumer<APIMockTomcat> server, Consumer<Mech2WithURI> client) {
try (APIMockTomcat mock = new APIMockTomcat()) {
server.accept(mock);
mock.start();
URI uri = mock.getURI();
Mech2WithURI mech2 = new Mech2WithURI(new Mech2(), uri);
client.accept(mech2);
}
}