web-dev-qa-db-ja.com

whennew()を介したpowermockモックコンストラクターは、匿名クラスでは機能しません。

DummyResourceクラスとDummyTargetファイル、およびテストクラスTestDummyResourceがありますが、モックされたオブジェクトDummyResource dr = mock(DummyResource.class)は、通常のクラス内でコンストラクターを呼び出したときにのみ機能し、匿名クラスで呼び出された場合、モックされたオブジェクトを使用する代わりに、実際のコンストラクターを呼び出します。

バージョン:

powermock 1.4.12 mockito 1.9.0 junit 4.8.2

DummyTarget.Java:

import Java.io.IOException;
import Java.io.OutputStream;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;


public class DummyTarget {
    public StreamingOutput testMocking() {
        return new StreamingOutput() {
            @Override
            public void write(OutputStream arg0) throws IOException, WebApplicationException {
                new DummyResource();
            }
        };
    }
}

DummyResource.Java:

package com.smin.dummy;

public class DummyResource {
    public DummyResource() {
        System.out.println("mock failure");
    }
}

TestDummyResource.Java:

package com.smin.dummy;

import static org.mockito.Mockito.mock;

import Java.io.IOException;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest({DummyResource.class,DummyTarget.class})
public class TestDummyResource  {

    @Before
    public void setUp() throws Exception {
        DummyResource dr = mock(DummyResource.class);
        PowerMockito.whenNew(DummyResource.class).withNoArguments().thenReturn(dr);
    }

    @Test
    public void testMocked() throws WebApplicationException, IOException {
        new DummyResource(); // it uses the mocked object dr here, 
                             //doesn't print "mock failure"
        StreamingOutput sop = new DummyTarget().testMocking();
        sop.write(null);     // it calls DummyResource's constructor,
                             // prints ""mock failure"" here
    }
}
20
Shengjie

匿名クラスは、それを定義するクラスのパッケージを継承するようです。 PrepareForTest のワイルドカード形式を試すことができますか?:

@PrepareForTest("com.smin.dummy.*")

それでも解決しない場合は、ショットガン PrepareEverythingForTest Annotationを試してください。

14
Brian Henry

コンストラクターが呼び出されるクラスではなく、コンストラクターを呼び出すクラスを準備しておく必要があります。以下を修正する必要があります。

@PrepareForTest(DummyTarget.class)

詳細については、 this ページを確認してください。

36
zbrunson

実際には、コンストラクターが呼び出されたクラスではなく、コンストラクターを呼び出すクラスをテストする準備をする必要があります。 https://github.com/jayway/powermock/wiki/MockConstructor を参照してください。

あなたの場合、@ PrepareForTest(DummyTarget.class)を使用する必要があります

9

同じ問題が発生し、完全修飾名のwhenNewを使用して解決しました。あなたの場合の内部匿名クラスの完全修飾名は次のとおりです。

DummyTarget.class + "$1"

そのため、そのクラスのモックを作成する必要があります。

DummyResource dr = mock(Class.forName(DummyTarget.class + "$1"));

そしてそれはあなたのために働くでしょう。

また、DummyTargetクラスを準備することを忘れないでください:

@PrepareForTest(DummyTarget.class)

役に立てば幸いです=]

0
Slava Shpitalny