Tsutomu Yano
benbr****@mac*****
2008年 12月 9日 (火) 00:29:09 JST
矢野です。 たいへん古いポストへの返信ですが、最近仕事で同じような機能を実装するに当たって 同じ状態に陥って、調査した結果解決できたので報告です。 この記事の件です。 2008年4月24日 1:10:16:JST > こんばんは。田中(u1)です。 > > WicketTesterのCookie処理で困っています。 > > ログイン時にログイン情報をクッキーに保存し、クッキーの値が取得できないと強制ログアウトするような作りのアプリを作っています。ここで、ログイン処理の単体テストを作成しようとしたのですが、うまくいきません。 > > ログイン処理成功時にクッキーを保存し、forwardしてログイン後ページに遷移する際に認証が必要なページなのでクッキーを参照するのですが、WicketTesterのMockHttpServletResponseにクッキーを設定してもMockHttpServletRequestにクッキーが反映されない(JBOSS、Jettyだと反映される)為、強制ログアウトされてしまいます。 > > リクエスト前に普通にCookieを設定する方法については、以下のようにWicketTesterのsetupRequestAndResponseで無理矢理Cookieを設定してやれば使用できることはわかりましたが、1リクエスト中にCookie設定→参照となると方法が見つかりません。 > @Override > public WebRequestCycle setupRequestAndResponse(final boolean isAjax) { > WebRequestCycle cycle = super.setupRequestAndResponse(isAjax); > if (!cookies.isEmpty()) { > ((MockHttpServletRequest) ((WebRequest) > cycle.getRequest()).getHttpServletRequest()).setCookies(cookies > .toArray(new Cookie[cookies.size()])); > } > return cycle; > } > > MockHttpServletResponse、Request自体を拡張しようかと考えましたが、WicketTesterの親クラスであるMockWebApplicationクラスのコンストラクタで生成してprivateメンバに設定、コンストラクタ中で使用されており、手が出せませんでした。 WicketTesterを調査したところ、ページ遷移の時にWicketTester内部でRequestCycleが再作成されて、そこで クッキーが引き継がれないために起こるようでした。 英語メーリングリストで似たようなケースの回答を見つけて、その回答についていたコードをヒントにして さらに追いかけてやっとわかりました。 WicketTesterの拡張クラスを次のように作ると、遷移してもCookieが引き継がれるようになります。 newRequestCycleをオーバーライドして、Cookieを引き継ぐ処理を行っています。 publicメソッドとして用意したaddCookieメソッドを使うことで、テストコード上からCookieを追加することも できます。 public class CookieAwareWicketTester extends WicketTester { protected Collection<Cookie> cookies = Generics.newArrayList(); public CookieAwareWicketTester() { } public CookieAwareWicketTester(Class<? extends Page> homePage) { super(homePage); } public CookieAwareWicketTester(WebApplication application) { super(application); } public CookieAwareWicketTester(WebApplication application, String path) { super(application, path); } @Override public WebRequestCycle createRequestCycle() { WebRequestCycle cycle = super.createRequestCycle(); if (saveCookieState()) { transferCookies(); } return cycle; } /** * Should cookies be saved during request cycles? This means that all cookies from Response will * override any cookie in the Request * * @return true if request cycles should keep cookies */ protected boolean saveCookieState() { return true; } protected void transferCookies() { HttpServletRequest webRequest = getWicketRequest().getHttpServletRequest(); HttpServletResponse webResponse = getWicketResponse().getHttpServletResponse(); MockHttpServletRequest request = (MockHttpServletRequest)webRequest; MockHttpServletResponse response = (MockHttpServletResponse)webResponse; Collection<Cookie> newCookies = response.getCookies(); if(newCookies != null && newCookies.size() > 0) { cookies.addAll(newCookies); } if(cookies != null && cookies.size() > 0) { request.setCookies(cookies.toArray(new Cookie[0])); } } public void addCookie(Cookie cookie) { this.cookies.add(cookie); } } とりあえず将来同じ問題にかかる人のための記録としてポストしておきます。 --------------------------------------------------- 矢野 勉(やの つとむ) 電子メール:benbrand_at_mac.com ---------------------------------------------------