2011-11-29 12 views
16

継承された保護されたメソッドを模擬したい。別のパッケージのクラスから継承されているため、このメソッドをJavaコードから直接呼び出すことはできません。私はPowerMockito.whenオーバーライドを見て、これは彼らが唯一のプライベートメソッドのすべてであると思わwhen(...)mocking protected method

package a; 

public class A() { 
    protected int m() {} 
} 

package b; 

public class B extends a.A { 
    // this class currently does not override m method from a.A 
    public asd() {} 
} 

// test 
package b; 

class BTest { 
    @Test 
    public void testClass() { 
     B instance = PowerMockito.spy(new B()); 
     PowerMockito.when(instance, <specify a method m>).thenReturn(123); 
     //PowerMockito.when(instance.m()).thenReturn(123); -- obviously does not work 
    } 
} 

にでスタブするために、このメソッドを指定する方法を見つけることができません!

保護されたメソッドを指定する方法は?

+0

@AndroidKiller、クラス名で更新されたコード。実際にはMockitoのものかもしれませんが、私はpowermockを使用しています。これらのメソッドは同じ意味を持っています –

+0

これは、継承より常に合成を優先させるべき理由です。レガシーコードと同じように、テスト済みのコードでこのメソッドを再定義することはできません。 – Brice

答えて

24

Nutshell:スタブのスパイには常にwhenを使用できません。 doReturnを使用してください。 spydoReturn

と仮定すると、静的インポート(両方PowerMockitoは):

@RunWith(PowerMockRunner.class) 
@PrepareForTest(B.class) 
public class BTest { 
    @Test public void testClass() throws Exception { 
     B b = spy(new B()); 
     doReturn(42).when(b, "m"); 
     b.asd(); 
    } 
} 

また@PrepareForTest(A.class)when(a, "m")doReturnを設定することができます。実際のテストによりますます意味があります。

+0

うわー、ありがとう。興味深いことに、メソッド名の代わりにメソッドインスタンスを使用しようとしたとき、名前のスタブが失敗し、引数の数が間違っているという例外メッセージが表示されませんでした。しかし、文字列の名前はすべて完璧に動作します。 –

+0

@mishanesterenkoまあ、少し畳んでいることがあります。もう一つの選択肢は、テスト目的のために常に 'B'をサブクラス化することです。オプションではありませんが、バイトコードを変更するより "マジカル"に劣ります; –

+0

Methodeがvoidを返すように設定した場合はどうなりますか?例えば、mがvoid m(MySpecialParser parser)のようなset-Methodeであるとしましょう。このパーサーは私のテキストを解析するために使われます。どのように私はそれを笑うことができますか? – Kayser