[cubby-user:69] Re: CubbyTestCase における Action クラスへの値のバインディングについてのご報告

Takashi Someda [E-MAIL ADDRESS DELETED]
2008年 6月 3日 (火) 02:39:49 JST


染田です。

> 特に問題がなければ、頂いたコードをCubbyTestCaseに取り入れて、
> processActionの先頭でassembleする予定です。

先のメールの後で、一点手元ではまった
パターンがありましたので、お知らせしておきます。

ケースとしては、Form アノテーションで指定しているオブジェクトが
コンテナ管理下にある場合、テストケースの書き方によっては、
先の方法で assemble するとオブジェクトが変わってしまう事があります。
#  パターンとしては、コンテナで、バインドしている
#  モノは全て影響あるかもしれません。(未確認ですが・・・)

具体的には、以下のように formDto で、フォームオブジェクトを
バインディングしており、FormDto クラスは NamingConvention で
指定したパッケージ配下にあるものとします。

@Form("formDto")
public class BindingAction extends Action{

  public FormDto formDto;

  public ActionResult index(){
    return new Forward("index.html");
  }
}

としているときに、以下のようなテストケースがあったとします。

public class BindingActionTest extends CubbyTestCase{
  public BindingAction action;

  public void testIndex() throws Exception{
    FormDto formDto = new FormDto(); // (1)
    action.formDto = formDto;
    processAction("/binding/");
  }
}

修正を加える前は、既にコンテナ側で action オブジェクトが
assemble されており、その時点でバインディングされている
dto を上記の (1) のオブジェクトにて上書きするような形になります。
ですので、テスト実行時には、そのまま (1) のオブジェクトが利用されるような
形になります。

ところが、先述の reassemble の処理を入れた場合には、
(1) で設定した Dto はコンテナ外で生成したモノですので、
再度、assemble 処理をかけると、コンテナ配下のオブジェクトを
バインディングしてしまい、意図した振る舞いをしてくれなくなります。

(1) を

FormDto formDto = (FormDto) getComponent(FormDto.class);

と、コンテナ側から取得し、設定すれば問題は回避出来るのですが、
既存のテストケースで、上記のように Dto を new して、直接設定するような
テストを記述している場合には、assemble 処理を入れる事によって、
挙動が変わってしまう可能性があります。。。

この件に関しては、S2 コンテナの使い方の側面が強いのですが、
public フィールドは上記のような使い方も出来てしまうので、悩ましい所ですね。。。

以上、簡単ですがご報告でした。

染田

2008/6/1 AGATA Toshitaka <[E-MAIL ADDRESS DELETED]>:
> 縣です。
>
> 詳細な報告と改善案、ありがとうございます。
> (テストネタ大歓迎です)
>
>> して頂くか、もしくは processAction 前後で、該当のテストケースに
>> アクションがフィールド設定してある場合には、再度 assemble
>> するような処理を入れていただけると嬉しいかな、と思いご報告
>> させて頂きました。
>
> テストからのAction実行時も、プロパティのバインディングの挙動が、
> 通常のAction実行と同じ挙動になるように、対応したいと思います。
>
> 特に問題がなければ、頂いたコードをCubbyTestCaseに取り入れて、
> processActionの先頭でassembleする予定です。
>
> よろしくお願いします。
>
> Takashi Someda さんは書きました:
>> 染田です。
>>
>> またまたテストネタで申し訳ありません。
>>
>> Action クラスにおける、プロパティバインディングが非常に便利で
>> 利用させて頂いているのですが、TestCase 内に対象のアクションを
>> オートバインディングさせていると、S2Container 側で設定される暗黙
>> オブジェクトと、Cubby の InitializeInterceptor で設定される値に差異が
>> 生じます。
>>
>> 具体的に、以下の BindingAction のparam オブジェクト
>> (S2Container がバインド) と p (InitializeInterceptor がバインド)
>> というプロパティですが、BindingActionTest 内に BindingAction
>> 自身をフィールド設定しているか、いないかで結果が異なります。
>>
>> 前者のテストケース内に Action オブジェトをバインディング
>> している場合、param からの取得は null で、後者であれば、
>> どちらからも問題なく取得できます。
>>
>> ----- BindingAction -----
>> public class BindingAction extends Action {
>>
>>     public Map param;
>>
>>     public String p;
>>
>>     public ActionResult index() {
>>         System.out.println("parameter name p from field " + p);
>>         System.out.println("parameter name p from param map " + param.get("p"));
>>         return new Forward("index.html");
>>     }
>> }
>> ----- BindingActionTest -----
>> public class BindingActionTest extends CubbyTestCase {
>>
>>     // この値を設定するか否かで挙動が変わる
>>     public BindingAction action;
>>
>>     public void testIndex() throws Exception {
>>         getRequest().addParameter("p", "nice!!");
>>         processAction("/binding/");
>>     }
>> }
>> -----
>>
>> 一通りおってみたところ、テストケース内に、アクションクラスが
>> いる場合、S2Framework#bindFields がテスト実行前に呼ばれ、
>> そのタイミングで暗黙オブジェクトが設定されます。で、ActionProcessorImpl
>> 内では、そこで作られた Action を利用してしまうので、param などの
>> 暗黙オブジェクトは設定されないままとなっているようです。
>>
>> 手元では、以下のようなメソッドを processAction の呼び出し前に行い、
>> request.addParameter などがされた後の処理を入れて対応しています。
>> # 他にも良い方法あるかもしれないのですが。。。
>>
>> ----
>>     protected void reassemble() {
>>
>>         for (Class clazz = getClass(); clazz != CubbyTestCase.class
>>                 && clazz != null; clazz = clazz.getSuperclass()) {
>>             Field[] fields = clazz.getDeclaredFields();
>>             for (Field f : fields) {
>>                 if (Action.class.isAssignableFrom(f.getType())
>>                         && getContainer().hasComponentDef(f.getType())) {
>>                     Object component = getComponent(f.getType());
>>                     AutoPropertyAssembler assembler = new
>> AutoPropertyAssembler(getComponentDef(f.getType()));
>>                     assembler.assemble(component);
>>                 }
>>             }
>>         }
>>     }
>> ------
>>
>> cubby のドキュメントには、暗黙オブジェクトの記述も、
>> またテストケース内に、対象のアクションクラスをフィールド設定
>> する例も載っておりますので、ドキュメントに注意事項として記載
>> して頂くか、もしくは processAction 前後で、該当のテストケースに
>> アクションがフィールド設定してある場合には、再度 assemble
>> するような処理を入れていただけると嬉しいかな、と思いご報告
>> させて頂きました。
>>
>> 以上、よろしくお願い致します。
>>
>> 染田
>
>
> --
> -------------------------------
> 株式会社ヌーラボ 縣 俊貴
> Mail : [E-MAIL ADDRESS DELETED]
> HP   : http://www.nulab.co.jp/
> TEL  : 03-5766-6256(東京)
>      092-724-0020(福岡)
> -------------------------------
> _______________________________________________
> cubby-user mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/cubby-user
>



-- 
SOMEDA Takashi
[E-MAIL ADDRESS DELETED]
http://tuigwaa.sandbox.seasar.org


cubby-user メーリングリストの案内