2011-11-08 9 views
23

私はJNDI呼び出しを行っているプラ​​イベートメソッドを嘲笑しようとしています。そのメソッドがユニットテストから呼び出されると、例外がスローされます。テスト目的でこのメソッドを模擬したいと思います。 sample code from another questions answerを使用しましたが、テストに合格している間は、基本的なメソッドが呼び出されたようです。 doTheGamble()メソッドにSystem.err.println()を挿入し、自分のコンソールに出力します。PowerMockでプライベートメソッドを偽装しましたが、基本的なメソッドがまだ呼び出されました

最初にassertThatをコメントアウトすると、テストに合格します。 ?:(私のワークスペースにはJNDIをサポートしていないので、

だから、私はプライベートメソッドをモックんどのようにそれが呼び出されないように?

import static org.hamcrest.core.Is.is; 
import static org.junit.Assert.assertThat; 
import static org.mockito.Matchers.anyInt; 
import static org.mockito.Matchers.anyString; 
import static org.powermock.api.mockito.PowerMockito.when; 
import static org.powermock.api.support.membermodification.MemberMatcher.method; 

import java.util.Random; 

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(CodeWithPrivateMethod.class) 
public class PowerMock_Test { 

    static boolean gambleCalled = false; 

    @Test(expected = RuntimeException.class) 
    public void when_gambling_is_true_then_always_explode() throws Exception { 
     CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod()); 

     when(spy, method(CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class)) 
       .withArguments(anyString(), anyInt()) 
       .thenReturn(true); 

/* 1 */ assertThat(PowerMock_Test.gambleCalled, is(false)); 
     spy.meaningfulPublicApi(); 
/* 2 */ assertThat(PowerMock_Test.gambleCalled, is(false)); 
    } 
} 


class CodeWithPrivateMethod { 

    public void meaningfulPublicApi() { 
     if (doTheGamble("Whatever", 1 << 3)) { 
      throw new RuntimeException("boom"); 
     } 
    } 

    private boolean doTheGamble(String whatever, int binary) { 
     Random random = new Random(System.nanoTime()); 
     boolean gamble = random.nextBoolean(); 

     System.err.println("\n>>> GAMBLE CALLED <<<\n"); 
     PowerMock_Test.gambleCalled = true; 

     return gamble; 
    } 
} 

は当然のことながら、唯一の生産環境が

を行います^

%私はモックオブジェクトを構築するために、すべてのライブラリ、JUnitの4.10、Mockito 1.8.5、Hamcrest 1.1、Javassistの3.15.0、およびPowerMock 1.4.10。

答えて

29

@RunWith(PowerMockRunner.class) 
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods 
@PrepareForTest(PartialMockClass.class) 
public class YourTestCase { 
@Test 
public void privatePartialMockingWithPowerMock() {   
    PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass()); 

    // use PowerMockito to set up your expectation 
    PowerMockito.doReturn(value).when(classUnderTest, "methodToMock", "parameter1"); 

    // execute your test 
    classUnderTest.execute(); 

    // Use PowerMockito.verify() to verify result 
    PowerMockito.verifyPrivate(classUnderTest, times(2)).invoke("methodToMock", "parameter1"); 
} 

だからあなたのコードにこれを適用するために、私はそれがになるかもしれないと思う:

@RunWith(PowerMockRunner.class) 
@PrepareForTest(CodeWithPrivateMethod.class) 
public class PowerMock_Test { 
    @Test(expected = RuntimeException.class) 
    public void when_gambling_is_true_then_always_explode() throws Exception { 
     CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod()); 

     PowerMockito.doReturn(true).when(spy, "doTheGamble", anyString(), anyInt()); 


/* 1 */ PowerMockito.verifyPrivate(spy, times(0)).invoke("doTheGamble", anyString(), anyInt());    
     spy.meaningfulPublicApi(); 
/* 2 */ PowerMockito.verifyPrivate(spy, times(2)).invoke("doTheGamble", anyString(), anyInt());    
    } 
} 

私はちょうどここエディタでコード化されていること。実際にテストは実行されておらず、このコードの作成にはバグはありません。

+8

+1はバグの無害です。あなたのことを大切にしています;) – Guillaume

+0

@MikeなぜdoReturn(真)なのか、スパイ、doTheGamble、a​​nyString()、anyInt()); 'doReturn(true).when(スパイ、メソッド(CodeWithPrivateMethod.class、 "doTheGamble"、String.class、int.class)).withArguments(anyString()、anyInt()); '結果は' IllegalArgumentException:引数型不一致 'になりますか?後者は、例のスタイルと少なくとも同等に保たれているように見えますが、機能しません。 – ArtB

+0

正直、申し訳ありません。私は比較的Mockito/PowerMock自身に新しいです...私は以前にそのスタイル( '.withArguments(...)')でコードを書くことを試みたことはありません。 – Mike

0

あなたがspyを使うの最新バージョンを使用しています、本当のハーフバックオブジェクトです。 spyを取り除くべきである。 純粋なモックオブジェクトで作業してください。 PowerMock Private Method Exampleから

+1

私はこのスパイのクラスの実装をテストしようとしているので、これはオプションではありません。 – ArtB

1

ArtB、

あなたのコードが動作しない(または)私はここで何かが欠けていますが、確かではありますか?私はちょうどマイクが示唆され、以下の一つの方法であなたの方法期待を交換し、それが正常に動作します:

PowerMockito.doReturn(true).when(spy, 
       method(CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class)) 
       .withArguments(anyString(), anyInt()); 

私はPowermockitoを使用していないが、多くの前にMockitoを使用しません。

+0

はい私は確かに、仕事に出れば、出力をペーストするでしょう。 – ArtB

2

ArtB、ちょうど私のEclipse IDEで正常に動作し、完全なコードを貼り付け

。私は私の最後の投稿で言った期待を変えただけです。がんばろう。

import static org.hamcrest.core.Is.is; 
import static org.junit.Assert.assertThat; 
import static org.mockito.Matchers.anyInt; 
import static org.mockito.Matchers.anyString; 
import static org.powermock.api.support.membermodification.MemberMatcher.method; 

import java.util.Random; 

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(CodeWithPrivateMethod.class) 
public class PowerMock_Test { 

    static boolean gambleCalled = false; 

    @Test(expected = RuntimeException.class) 
    public void when_gambling_is_true_then_always_explode() throws Exception { 
     CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod()); 

//  PowerMockito.doReturn(true).when(spy, "doTheGamble", anyString(), anyInt()); 

     PowerMockito.doReturn(true).when(spy, 
       method(CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class)) 
       .withArguments(anyString(), anyInt()); 

     assertThat(PowerMock_Test.gambleCalled, is(false)); 
     spy.meaningfulPublicApi(); 
     assertThat(PowerMock_Test.gambleCalled, is(false)); 
    } 
} 


class CodeWithPrivateMethod { 

    public void meaningfulPublicApi() { 
     if (doTheGamble("Whatever", 1 << 3)) { 
      throw new RuntimeException("boom"); 
     } 
    } 

    private boolean doTheGamble(String whatever, int binary) { 
     Random random = new Random(System.nanoTime()); 
     boolean gamble = random.nextBoolean(); 

     System.err.println("\n>>> GAMBLE CALLED <<<\n"); 
     PowerMock_Test.gambleCalled = true; 

     return gamble; 
    } 
} 
関連する問題