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

BABA,Yasuyuki [E-MAIL ADDRESS DELETED]
2008年 6月 4日 (水) 23:09:14 JST


馬場です。

遅くなりましたがちょっといろいろ試してみました。

AutoPropertyAssembler#assemble を実行するよりも、リクエストパラメータは
setUpメソッドで設定するのがハマりどころが少ないと思いますがどうでしょう?
以下の例だと、reassemble() メソッドが追加される前の CubbyTestCase でも両
方 "nice!!" が出力されます。

public class BindingActionTest extends CubbyTestCase {

	public BindingAction action;	// (1)

	protected void setUp() {
		include("app.dicon");
	}

	public void setUpIndex() {
		getRequest().addParameter("p", "nice!!");
	}

	public void testIndex() throws Exception {
		processAction("/binding/");
	}

}


Takashi Someda さんは書きました:
> 染田です。
> 
>> 特に問題がなければ、頂いたコードを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
>>
> 
> 
> 


-- 
BABA,Yasuyuki
[E-MAIL ADDRESS DELETED]


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