m-namikiの日記

おもしろき こともなき世を おもしろく

Mockを使ったjUnitテスト

何故かS2ContainerのドキュメントからMockInterceptorの使い方ガイドが外れているようなのでメモ。
http://s2container.seasar.org/2.4/ja/testtech.html
多分これからはEasyMockを使いなさいってことなんだろうけど、EasyMockは使い方がよく分からないからMockInterseptorでテストケースを書いてみる。TDDの原則から言うとテストケースを最初に書くのが正しいんだけど。

まずはテスト対象となるLoginAction。

public class LoginAction extends BaseAction {
    public String userId;
    public String password;
    public UserService userService;
    public ActionResult process() {
        User user = userService.login(userId, password);
        if (null != user) {
            // 認証成功
               :
        } else {
            // 認証失敗
            errors.add("ユーザーIDまたはパスワードが違います。");
            return new Forward("/login/login.html");
        }
        return new Redirect("/menu/");
}

LoginActionのテストケースを書く際に、UserServiceをMock化したいのでsrc/test/resourcesにLoginActionTest.diconを作成して、MockInterceptorの設定を記述する。

<!-- LoginActionTest.dicon -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.3//EN"
  "http://www.seasar.org/dtd/components23.dtd">
<components>
  <component name="userServiceMI" class="org.seasar.framework.aop.interceptors.MockInterceptor"/>
  <component name="userService" class="com.example.service.UserService">
    <aspect>userServiceMI</aspect>
  </component>
</components>

そして実際のテストケース。

public class LoginActionTest extends CubbyTestCase {
    private LoginAction action;
    private MockInterceptor userServiceMI;

    public void testProcess_ログイン失敗() throws Exception {
        getRequest().setParameter("userId", "aaaaa");
	getRequest().setParameter("password", "aaaaa");

	// UserService#login()がnullを返すように設定 = ログイン失敗
	userServiceMI.setReturnValue("login", null);
		
        ActionResult result = processAction("/login/process");
	assertPathEquals(Forward.class, "/login/login.html", result);
		
	assertFalse("エラーメッセージが登録されていること"
	        , action.getErrors().isEmpty());
		
	ActionErrors errors = action.getErrors();
	List<String> list = errors.getAll();

        assertEquals("エラーメッセージは一つだけ登録されていること", 1, list.size());
	assertEquals("ログイン失敗メッセージが登録されていること"
			, "ユーザーIDまたはパスワードが違います。", list.get(0));
    }
}

テストケースはわざと日本語のメソッド名にしている。これはWEB+DB PRESSのVol.35で和田さんが紹介していたのを読んでから始めたんだけど、メソッド名だけで何をしようとしているのか一目で分かって便利。
さて、これでテストケースの書き方も分かったし、これからは今まで作ってきたクラスのテストケースも平行して書いていく。それからまだ出来ていないクラスは先にテストを書くようにしないと。EasyMock版はどうしようかな。