Challenge Engineer Life !

エンジニア人生を楽しみたい!仕事や趣味で学んだ技術的なことを書いていくブログです。

ArquillianのテストでFacesContext.getCurrentInstance()がnullなのでモックを作る

昨年作ったJava EE6のプロトタイプにArquillianを使ったテストを入れてどんなことまでできるか確認してます。
単体レベルの試験も簡単にできるし、DB使った試験も簡単だし、かなり良い感じです。

とりあえず今のところ、躓いたのはFacesContext周辺。

画面サイドはSeleniumを利用してブラウザレベルでグルグルテストするので、Arquillianで画面サイドまではテストするつもりはないのですが、ログインのbacking beanの中で、ログ出力のためにクライアントのIPアドレスを取得するような以下プログラムがあって

private String getRemoteIpAddr(){
    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
    HttpServletRequest request = (HttpServletRequest)externalContext.getRequest();
    return request.getRemoteAddr();
}

テストすると、FacesContext.getCurrentInstance()がnullとなってしまって失敗してしまいます。この辺はJSFUnitを使う、という記事がありましたが、今の所そこまで気合い入ってなくて、ここをちょいと抜けてくれればいいんだけど…という思いがありました。

元のコードを変えて、そもそもFacesContext.getCurrentInstance()がnullの場合は、みたいな分岐エラー処理を入れてもいいかと思ったのですが…うーん、どうしよう、と。

悩んでいる中「FacesContext null test」とかでググってたら、そもそもArquillian関係なく、JUnitでbacking beanをテストするケースがあって、同じように困っている人が多々。

で、対策の1つにモックを使う方法がありました。なるほど。

参考にさせて頂いたのは「JSF:mocking FacesContext for unit tests」の記事です。

記事にあるContextMockerクラスをお借りして、以下コードをお試ししたら、ちゃんとテストできました!

モック作りにMockitoを使うので、まずはpom.xmlに記述

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <version>1.9.5</version>
    <scope>test</scope>
</dependency>

ContextMockerクラスはテストパッケージ内に作成しました。

ログインのbacking beanのログイン処理をテストします
ログイン成功時の戻り値は画面遷移先のURLなので、それを比較します。

@Test
public void ログイン成功のテスト(){
    FacesContext context = ContextMocker.mockFacesContext();
    ExternalContext ext = mock(ExternalContext.class);
    HttpServletRequest request = mock(HttpServletRequest.class);
        
    when(context.getExternalContext()).thenReturn(ext);
    when(ext.getRequest()).thenReturn(request);
    when(request.getRemoteAddr()).thenReturn("10.255.255.1");

    loginBean.setUserId("horikita");
    loginBean.setPassword("makimaki");
        
    assertThat(loginBean.login(), is("/opportunity/opportunityList.xhtml"));
}

テストの結果
f:id:kikutaro777:20130111172432j:plain
どーん。やったー!JSFUnitまで手を出すのはしんどいなぁと思っていたのですが、これなら簡単なので、良い感じです。すごいー。

にほんブログ村 IT技術ブログへ
にほんブログ村 にほんブログ村 IT技術ブログ Javaへ
にほんブログ村