Index: [Article Count Order] [Thread]

Date:  Fri, 15 Oct 2004 16:22:45 +0900
From:  MIYAMUKO Katsuyuki <k-miyamuko@....com>
Subject:  [XP-jp:05078] Re: DbC on Java/C#...
To:  extremeprogramming-jp@....jp
Message-Id:  <416F7AC5.8060209@....com>
In-Reply-To:  <200410150631.i9F6VXN00461@....jp>
References:  <200410150631.i9F6VXN00461@....jp>
X-Mail-Count: 05078

みやむこといいます。

>> 中でやってることは、リフレクションでメソッド読んでるだけです。
>>	protected Object executeMethod(Object aObject
>>								  ,String aMethodName
>>								  ,Class[] aParameterTypes
>>								  ,Object[] aParameterValues) {
>>
>> こんな感じで。
> 
> 
> ですよねぇ。valueはともかく、typeの列が面倒やし、
> これしくじるとテストしてんだかされてんだかわかんねぇ ^^;

私の場合は dynamic proxy を利用して private method をテストしています。

まず、proxy を作成するクラスを作っておきます。
PrivateAccessor は junit-addons に含まれています。

    public final class PrivateProxy {
        public static Object createProxy(final Object target, Class interfaceClass) {
            InvocationHandler h = new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    return PrivateAccessor.invoke(target,
                                                  method.getName(),
                                                  method.getParameterTypes(),
                                                  args);
                }
            };

            return Proxy.newProxyInstance(interfaceClass.getClassLoader(),
                                          new Class[] { interfaceClass }, h);
        }
    }

で、テスト対象のこんなクラスがあったとします。

    class TestTarget {
        private long compute(long v) {
            return v * 13;
        }
        private long compute2(long v) {
            ...;
        }
    }

まず、テストしたい private メソッドを定義した interface を作成します。

    interface PublicTestTarget {
        public long compute(long v);
        public long compute2(long v);
        ...
    }

target の private メソッドを起動する proxy を作成します。

    TestTarget target = new TestTarget();
    PublicTestTarget publicTarget = (PublicTestTarget) PrivateProxy.createProxy(
        target, PublicTestTarget.class);

あとは assert。

    assertEquals(1300, publicTarget.compute(100));

--

でも、テスト対象のメソッドのシグネチャが変わったら interface も直す必要がある
ので面倒なことは面倒なんですよね。

まぁ、こういうことをしないとテストできない時点で設計がおかしいとは思うんですけど。
なかなか難しいですね。