ウィリアムのいたずらの、まちあるき、たべあるきーPART2

gooブログ「ウィリアムのいたずらの、まちあるき、たべあるき」がお引越ししてきました

【お題】Struts2でdjunitしたい(ServletRequestAwareを実装)

前に、

Strutsの単体テスト StrutsTestCase for JUnitの使い方(16日追加)
http://blog.goo.ne.jp/xmldtp/e/aba8bac027597bd6e39c4d54f2f62c5a

で、Struts1の単体テストの話をした。
で、Struts2でJUnitテスト、djunitテストをしたい場合は?

SessionAwareやServletRequestAwareを使っていない場合は、問題ない。
そのまま、呼び出してくれればよい。

SessionAwareなら、まだまし。
HashMapをsessionにみたてて、そのMapをsetSessionで渡せばOK

問題は、ServletRequestAware。
これは、Tomcatが使っているCoyoteRequestとか、Requestとか
使おうとすると、いろいろたいへん(依存性とかあって・・・*注1)
で、どうするか?というのが、今日のお題。




【対応策例】Struts1のときに使ったstrutstestを使おう!

 上記Struts1の単体テストの話のときに使ったstrutstestの中に、

  servletunit.HttpServletRequestSimulator

 というのがいるので、こいつを使う。
 こいつは、setParameterができる。




【やってみよう】

・前提
 eclipseでやる→JUnitは標準的に作れる
 djunitは、いれたものとする(注2)
 strutstestは、ダウンロードしてあって、解凍してでてきたjarに対して
 作成するプロジェクトから、クラスパスが貼られている
 (プロジェクトで右ボタン、プロパティのJavaのビルド・パスで
  外部jar追加を行った) (注3)

 テスト対象クラスは、こんなかんじ
package struts2.gui;

//	セッションで使う
import java.util.Map;

//(1)リクエストで使うものインポート
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.SessionAware;

//	一般的に・・・
import com.opensymphony.xwork2.ActionSupport;

//==============================================//
//												//
//	Struts2										//
//	セッション、リクエストのサンプル			//
//												//
//==============================================//
public class HelloAction extends ActionSupport implements SessionAware,ServletRequestAware{
	private String name;						//	sタグの変数
	private String msg;

	private Map<String,Object> session;						//	セッションの宣言
	private HttpServletRequest request;			//	(2)リクエストの宣言

	//	sタグで必要なアクセサ
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

	//	セッションで必要なアクセサ
	public void setSession(Map<String,Object> session) {
		this.session = session;
	}

	//	(3)リクエストで必要なアクセサ記述
	public void setServletRequest(HttpServletRequest request) {
		this.request = request;
	}

	public HttpServletRequest getServletRequest() {
		return this.request;
	}

    public String execute()
    {
  	    //======================================//
  	    //		値の取得						//
  	    //======================================//
    	// sタグのnameは、何もしなくても取得されている

    	//	セッションでの取得
  	    int	kai;
  	    String kaistr = (String)session.get("kaisu");
  	    if ( kaistr	==	null)
  	    {
  	    	kai	=	0;
  	    }
  	    else
  	    {
  	    	kai = Integer.parseInt(kaistr);
  	    }

  	    //	(4)リクエストパラメタでの取得
  	    String start = getServletRequest().getParameter("start");
  	    if (start	!=	null)
  	    {
  	    	try
  	    	{
  	    		kai =  Integer.parseInt(start);
  	    	}
  	    	catch(Exception e)
  	    	{
  	    		//	数字でなかったら、なにもしない
  	    	}
  	    }


  	    //======================================//
  	    //		処理							//
  	    //======================================//
  	    kai++;		//	今回の分を足す
  	    setMsg("Hello World" + name + ":"+ kai+"回目");


  	    //======================================//
  	    //		出力								//
  	    //======================================//
  		//	セッション書き出し
  		session.put("kaisu", String.valueOf(kai));
  		session.put("msg", getMsg());

        this.addActionMessage("成功1");
        return SUCCESS;
    }
}


・テストするクラスを作る
 そこから、sessionは
HashMap<String,Object> session = new HashMap<String,Object>(); // セッションの作成
test.setSession(session);

 なかんじで、HttpServletRequestは、
HttpServletRequestSimulator request
= new HttpServletRequestSimulator(new ServletContextSimulator()); // HttpServletRequestの代わり作成
test.setServletRequest((HttpServletRequest)request);

なかんじでセットする
 以下のソースのかんじ

package struts2.gui;

import static org.junit.Assert.*;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
import org.junit.Test;

//==================================
// HttpServletRequestのかわりに必要
//==================================
import servletunit.HttpServletRequestSimulator;
import servletunit.ServletContextSimulator;

public class HelloActionTest {

@Test
public void test() {

//============================================
// いろいろ設定
//============================================
// 作成する
HelloAction test = new HelloAction();

// SessionAware設定
HashMap<String,Object> session = new HashMap<String,Object>(); // セッションの作成
test.setSession(session);

// ServletRequestAware設定
HttpServletRequestSimulator request
= new HttpServletRequestSimulator(new ServletContextSimulator()); // HttpServletRequestの代わり作成
test.setServletRequest((HttpServletRequest)request);
String ret;

//============================================
// テスト実行
//============================================

// 1回目
ret = test.execute();
assertTrue(ret.equals("success"));
assertTrue(((String)session.get("kaisu")).equals("1"));

// 2回目
ret = test.execute();
assertTrue(ret.equals("success"));
assertTrue(((String)session.get("kaisu")).equals("2"));

// 3回目
String[] args = new String[1];
args[0] = "1";
request.setParameterValue("start", args);
ret = test.execute();
assertTrue(ret.equals("success"));
assertTrue(request.getParameter("start").equals("1"));

// 4回目
ret = test.execute();
assertTrue(ret.equals("success"));

}

}



・実行すると、こんなかんじ





*注1:HttpServletRequestはインターフェースなので、実際に使うには
実装しているはず。

Tomcat5では、CoyoteRequestで実装しているらしい
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=9845&forum=12

Tomcat7では、
http://www.coderanch.com/t/567946/Java/java/Java-Tomcat-Java-Tomcat
によると、CoyoteRequestがRequestになったらしい
このRequestは、catalina.jarのorg.apache.catalina.connector.Request
にいるが、こいつを使おうとすると、いろんなものをリンクしないとエラーになる。


*注2
入れ方については
テストを楽にっ!!「djUnit」によるJavaソーステスターへの道
http://maplesystems.co.jp/blog/all/programming/11326.html
の「導入方法」を参照。大事なことは、指定するロケーションのURLは
http://works.dgic.co.jp/djunit/update/3.5.x/site.xml
ってこと。それ以降の使い方については
http://www.mitchy-world.jp/java/test/djunit.htm
を参照のこと。


*注3
ダウンロードURLは、
http://sourceforge.net/projects/strutstestcase/files/