- - PR -
MockObjectを使ったサーブレット&JSPのテストケースについて
| 投稿者 | 投稿内容 | ||||
|---|---|---|---|---|---|
|
投稿日時: 2004-03-03 12:59
サーブレットからJSPを呼び出す部分を
-------------------------------------------------------------------------------- ServletContext sc = getServletContext(); sc.getRequestDispatcher("http://localhost:8080/TestCase/Error.jsp").forward(req,res); -------------------------------------------------------------------------------- と定義してますがNullPointExceptionになってしまいます。 おそらくServletContextがテストケースで設定していないために、getServletContext()でエラーが出てると思い、MockServletContextを設定しようと次のようにしました。 -------------------------------------------------------------------------------- import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.mockobjects.dynamic.Mock; import com.mockobjects.dynamic.OrderedMock; import com.mockobjects.helpers.ServletTestHelper; import com.mockobjects.servlet.MockServletContext; import junit.framework.TestCase; public class ContributionCheckTest extends TestCase { Mock mockHttpServletRequest = new Mock(HttpServletRequest.class); Mock mockHttpServletResponse = new OrderedMock(HttpServletResponse.class, "Response with non-default name"); ContributionCheck aServlet = new ContributionCheck(); final StringWriter output = new StringWriter(); final PrintWriter contentWriter = new PrintWriter(output); final ServletTestHelper helper = new ServletTestHelper(); //ここでエラーが出る final MockServletContext sc = helper.getServletContext(); public ContributionCheckTest(String arg0) { super(arg0); } public static void main(String[] args) { junit.swingui.TestRunner.run(ContributionCheckTest.class); } public void testSimpleAddition() throws ServletException, IOException { mockHttpServletResponse.expect( "setContentType", "text/html"); mockHttpServletResponse.expectAndReturn( "getWriter", contentWriter ); aServlet.doGet((HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy()); mockHttpServletRequest.verify(); mockHttpServletResponse.verify(); } } -------------------------------------------------------------------------------- new ServletTestHelper()にはHttpServletを引数にしないといけないようなのですが、 この部分がよくわかりません。 そもそも final ServletTestHelper helper = new ServletTestHelper(); final MockServletContext sc = helper.getServletContext(); このようにServletContextを設定する考え方が間違っているのでしょうか? MockServletContextクラスのgetContext(java.lang.String arg0) メソッドを使ったほうが良いのでしょうか? この場合に引数でどんな値を送ればいいのかがわかりません。 どなたかご教授お願いいたします。 | ||||
|
投稿日時: 2004-03-03 15:48
最初の質問のサーブレットからJSPを呼び出す部分を
-------------------------------------------------------------------------------- ServletContext sc = getServletContext(); sc.getRequestDispatcher("http://localhost:8080/TestCase/Error.jsp").forward(req,res); -------------------------------------------------------------------------------- から -------------------------------------------------------------------------------- RequestDispatcher rd = req.getRequestDispatcher("/Bulletin.jsp"); //reqはHttpServletRequest rd.forward(req,res); -------------------------------------------------------------------------------- に変更して ServletTestHelper MockServletContext を使用しないで実行したところ -------------------------------------------------------------------------------- junit.framework.AssertionFailedError: mockHttpServletRequest: Unexpected call: getRequestDispatcher(</Bulletin.jsp>) Expected one of: getParameter(< = a>) [called] getParameter(< = b>) [called] at com.mockobjects.dynamic.Mock.invoke(Mock.java:91) at $Proxy0.getRequestDispatcher(Unknown Source) at ContributionCheck.doGet(ContributionCheck.java:64) at ContributionCheckTest.testSimpleAddition(ContributionCheckTest.java:58) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at junit.framework.TestCase.runTest(TestCase.java:154) at junit.framework.TestCase.runBare(TestCase.java:127) at junit.framework.TestResult$1.protect(TestResult.java:106) at junit.framework.TestResult.runProtected(TestResult.java:124) at junit.framework.TestResult.run(TestResult.java:109) at junit.framework.TestCase.run(TestCase.java:118) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:392) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:276) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:167) -------------------------------------------------------------------------------- とエラーが出ました。 このやり方の場合は相対パスしか指定できないらしく、やはりテストケースのMockObjectで そこまでのパスを設定しなくてはならないのでしょうか? HttpServletRequestに設定するのでしょうか?(MockObject) その場合どのようにすればよいのかわかりません。 | ||||
|
投稿日時: 2004-03-04 14:45
RequestDispatcher rd = req.getRequestDispatcher("/Bulletin.jsp"); //reqはHttpServletRequest
のこれはどのような値をrdに入れているのでしょうか? 指定されたパスに位置するリソースのラッパとして動作する RequestDispatcher オブジェクトを返しているとAPIリファイレンスには書いてありますが、 「指定されたパスに位置するリソースのラッパとして動作する」とはどのようなものかがわかりません。 これをMockObjectで作成できるのでしょうか? 誰かご教授お願いいたします。 | ||||
|
投稿日時: 2004-03-08 12:12
サーブレットのテストの部分は自己解決ができました。
MockObjectでreq.getRequestDispatcherとされた時に RequestDispatcherの擬似オブジェクトをリターンするという形を取りました。 サーブレットはこれで良いのですが、JSPはどうするんでしょうか・・・ JSPに関してはMockオブジェクトの使い方がいまいちわかりません。 MockObjectでコンテナを作りテストをする、という形でできるらしいのですが、 みなさんはどのような形でテストをしていますか? | ||||
|
投稿日時: 2004-03-08 14:21
JSP は実行環境でコンパイルされてサーブレットに変換されますので、実行環境を用意しないMockアプローチでのテストは難しそうですね。
そもそもモデルとコントローラさえしっかりユニットテストができていればプレゼンテーション層それほど問題は発生しにくいものです。 どうしても必要なら実際にお使いのコンテナのJSPコンパイラでコンパイルしたものをサーブレットと同じ方法でテストしてみてはいかがでしょうか。実行環境なしにそのまま動くかどうかはわかりませんが・・・。 [ メッセージ編集済み 編集者: インギ 編集日時 2004-03-08 14:24 ] | ||||
|
投稿日時: 2004-03-08 17:31
インギさん返信ありがとうございます。
>どうしても必要なら実際にお使いのコンテナのJSPコンパイラでコンパイルしたものをサーブレットと同じ方法でテストしてみてはいかがでしょうか。 この方法ですと、コンテナはtomcatを使っていて、Eclipsで作っていますので、 JSPをコンパイルした後に、JAVAファイルのインポートをわざわざしないといけなくなってしまうので、できれば違う方法でやりたいと考えています。 パラメータを渡して正常に動くかをテストしたいので、 Tomcatを動かしている状態でJUnitからJSPを呼び出してテストするという形を取ろうと考えたのですが、req.getRequestDispatcher()が上手くいかないとできません。 サーブレットではRequestDispatcherが実際の動きをしなくてもforwardが実行されたかを確認すればよかったので、MockRequestDispatcherを使えば良かったのですが、今回は実際にJSPが呼ばれないといけないので、この部分を何とかしようと思っていますが、 ServletContextにgetRequestDispatcher()がどの値を設定すれば動くかわからなくてできません。 | ||||
|
投稿日時: 2004-03-08 23:56
Eclipseのどのプラグインを使っているのか分かりませんが、Sysdeo Tomcat Launcher pluginを 使った場合、JSPから変換されたサーブレットのソースがプロジェクト内のworkフォルダに 作成されます。そうでなくても、server.xmlのContextタグの属性workdirにプロジェクト内の フォルダを指定することで同等のことを実現できます。 ところでJSPのテストケースを作成したいとのことですが、 テストしやすいようにJSPを書かないとかなり複雑になるので注意した方がいいです。 実際にやってみた経験から言えば、JSPを、テストケースが不要でも安心できる程度に シンプルに作り、必要となる複雑な処理はJSPの呼び出し側(サーブレットなど)や タグライブラリに持って行った方がいいと思います。その方がJSPの保守性も上がりますから。 | ||||
|
投稿日時: 2004-03-09 11:22
koeさん返信ありがとうございます。
JAVAファイルはプロジェクト内のworkフォルダに作成されますが、インポートしないとEclipsから参照ができません。 workフォルダの中身はパッケージがorg.apache.jspとなっていて、参照ができません。 なぜかその中にはファイルが無い扱いになっています。 それで、そこにファイルをインポートしようとしたら、ファイルが存在しますと言われてしまいインポートできません。 一旦別の場所にインポートしてからそこに移動させればできますが・・・ この作業を一回やると、次回からはJSPを更新するたびにJAVAファイルが更新されるようです。 ですが、新しいJSPを作成するたびにこれをやるのはどうかと思います・・・ プラグインはcom.sysdeo.eclipse.tomcat_2.2.1を使っています。 プラグインをSysdeo Tomcat Launcher pluginに変えればできるのでしょうか? JSPでテストしたい部分は引数を受け取って、正常な値ならまともに動作して、異常ならエラーにするというテストだけなので、テスト自体は簡単なものです。 JUnitからreq.getRequestDispatcher("/hogehoge.jsp").forward(req,res)を正常に動作させる方法は無いのでしょうか? | ||||
