fc2ブログ
ホーム   »  Java  »  JavaScriptを使用するアプレットの単体テスト

JavaScriptを使用するアプレットの単体テスト

JavaScript を呼び出す Java アプレットを JUnit などで単体テストする場合、当然ながら正式なアプレットの実行環境ではないため JSObject#getWindow() の呼び出しで例外が発生してしまうことになる。テストのために JSObject を自作のスタブで置き換えられると便利であろう。今回はこの JSObject の置き換えについて調べてみる。なお調査に使用する JDK は以下の通りである。

java version "1.5.0_10"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_10-b03)
Java HotSpot(TM) Client VM (build 1.5.0_10-b03, mixed mode, sharing)

まず netscape.javascript.JSObject のクラスファイルを紐解いてみよう。格納されている JAR ファイルは以下の通りである。

{$java.home}\jre\lib\plugin.jar

この JAR ファイルから JSObject のクラスファイルを取得し、javap のアセンブラコードを手作業で復元して試行錯誤した結果、肝心な部分のコードは以下のように記述されるようだ。

public abstract class JSObject{
  // ...
  public static JSObject getWindow(Applet applet) throws JSException{
    JSObject jsobject;
    if(applet != null){
      try{
        String mayscript = applet.getParameter("MAYSCRIPT");
        AppletContext context = applet.getAppletContext();
        jsobject = null;
        if(context instanceof JSContext){
          JSContext jscontext = (JSContext)context;
          jsobject = jscontext.getJSObject();
        }
        if(jsobject != null){
          return jsobject;
        }
      } catch(Throwable ex){
        throw new JSException(
          JSException.EXCEPTION_TYPE_ERROR, ex);  // at JSObject.java:159
      }
    }
    throw new JSException();    // at JSObject.java:162
  }
}

どうやらアプレットが保持している AppletContextsun.plugin.javascript.JSContext のサブクラスとして実装すればスタブへ差し替えが可能なようだ。 この JSContextJSObject getJSObject() というメソッドをひとつだけ持つインターフェースなので、以下のような手順で JSObject のスタブ化が可能である。

  1. netscape.javascript.JSObject のサブクラスを作成する。これが今回の目的となるスタブである。
  2. sun.plugin.javascript.JSContextjava.applet.AppletContext の両方を implement したクラスを作成し、その getJSObject() メソッドで 1. で作成したクラスのインスタンスを返させる。
  3. java.applet.AppletStub のサブクラスを作成し、その getContext() メソッドで上記 2. で作成したクラスのインスタンスを返させる (必要なアプレットパラメータがあればそれも返すように実装すると良い)。
  4. テスト対象のアプレットのインスタンスを生成した後、init() の呼び出し前に setStub() で上記 3. で作成したアプレットスタブを設定する。

具体的には以下のようなコーディングになる。 なお、アプレットパラメータの MAYSCRIPT 値は参照しているだけで評価には使用されていない様子。実際、何も設定されていなくても JSObject#getWindow() は成功する。

public class MyAppletTest extends TestCase{
    public void testSomeFunctionThatCallsJSObject(){
        Applet applet = new MyApplet();
        applet.setStub(new MyAppletStub());
        applet.init();
        // ... アプレットの機能テスト
        applet.destroy();
        return;
    }
}

class MyAppletStub implements AppletStub{
    private final AppletContext context = new MyAppletContext();
    // ... AppletStub のインターフェースを実装
    public AppletContext getAppletContext(){
        return context;
    }
}

class MyAppletContext implements AppletContext, JSContext{
    private final JSObject jsobject = new MyJSObject();
    // ... AppletContext のインターフェースを実装
    public JSObject getJSObject(){
        return jsobject;
    }
}

class MyJSObject extends JSObject{
   // ... JSObject のメソッドを実装
}
参考:
コメント
トラックバック
トラックバック URL
コメントの投稿
管理者にだけ表示を許可する
Profile
Takami Torao
Takami Torao
C/C++ 使いだった 1996年、運命の Java と出会い現在に至る。のらアーキテクト。
Yah, this is image so I don't wanna eat spam, sorry!
Search

Google
MOYO Laboratory
Web

カテゴリー
最近の記事
最近のコメント
最近のトラックバック
月別アーカイブ
ブロとも申請フォーム
RSSフィード
リンク