ksino's diary

覚えたことを忘れないように、小さなことでも書いていく。

FacesContextを扱うクラスの単体テスト

FacesContext.getCurrentInstance().getViewRoot()とかやってるクラスの単体テストをやる必要がありました。しかし、単純にJUnitを起点にFacesContext.getCurrentInstance()が叩かれると、nullが返ってくるんですね。

どうしたもんだろ?と考えたのですが、mockitoを使うと簡単にできました。

↓こんなクラスの単体テストをやってみます。

import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;

public class TargetClass {
    public String method() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        UIViewRoot root = facesContext.getViewRoot();
        String viewId = root.getViewId();
        return viewId;
    }
}

mockitoを使うので、pom.xmlに追加します。

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

↓こんな感じでFacesContextのモックを作ります。

import javax.faces.context.FacesContext;
import org.mockito.Mockito;

public abstract class FacesContextMock extends FacesContext {

  public static FacesContext mock() {
    FacesContext context = Mockito.mock(FacesContext.class);
    setCurrentInstance(context); // FacesContextのメソッド
    return context;
  }
}

単体テストコードは↓こんな感じです。

import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;

public class TargetClassTest {
    
    @Test
    public void testMethod() {
        // モックの準備
        FacesContext context = FacesContextMock.mock();
        
        // テスト期待値の準備
        String viewId = "testViewId";
        UIViewRoot root = new UIViewRoot();
        root.setViewId(viewId);
        // getViewRootが呼ばれた時の戻り値を設定する
        Mockito.when(context.getViewRoot()).thenReturn(root);

        // テストメソッドの実行
        TargetClass target = new TargetClass();
        String actual = target.method();
        
        // 結果の検証
        Assert.assertEquals(viewId, actual);
    }
    
}

mockitoってすげー。