2017-01-23 182 views
2

我在實例化一個靜態的類的實例,並調用它的操作的類中的方法。懲戒靜態類

public class SomeClass { 
    public void someMethod() { 
     MyClass.MyStaticClass myStaticClassInstance = 
      new MyClass.MyStaticClass(arg1, arg2, arg3); 
     myStaticClassInstance.callSomeMethod(); 
    } 
} 

public class MyClass { 

    public static class MyStaticClass { 

     public MyStaticClass(Object arg1, Object arg2, Object arg3) { 
     } 

     public void callSomeMethod() { 
     } 
    } 
} 

如何嘲笑靜態類instanciation,這樣我就可以嘲笑callSomeMethod()沒有通過靜態類的構造函數去?

+0

喲你不應該首先在'SomeClass'中實例化'MyStaticClass'。您應該使用*依賴倒置*注入'MyStaticClass'的實例爲實例'SomeClass' –

回答

1

你可以嘲笑你的靜態內部類的實例與PowerMock做到這一點。這可以通過準備將實際實例化你的靜態內部類,所以這將是你有方法someMethod()類所定義的類來完成。

假設someMethod()被定義爲類MyOtherClass返回任何結果,您的測試類會是這樣的:

@RunWith(PowerMockRunner.class) // The runner of PowerMock 
@PrepareForTest(MyOtherClass.class) // the class to prepare 
public class MyClassTest { 

    @Test 
    public void test() throws Exception { 
     // The mock of your static inner class to return 
     MyClass.MyStaticClass mock = Mockito.mock(MyClass.MyStaticClass.class); 
     // Mock the call of callSomeMethod() 
     PowerMockito.doAnswer(
      new Answer<Void>() { 
       @Override 
       public Void answer(final InvocationOnMock invocation) throws Throwable { 
        // Do something here as new implementation of callSomeMethod 
        System.out.println("My new Answer"); 
        return null; 
       } 
      } 
     ).when(mock).callSomeMethod(); 
     // Return your mock in case we instantiate MyClass.MyStaticClass in 
     // the prepared class with any arguments 
     PowerMockito.whenNew(MyClass.MyStaticClass.class) 
      .withArguments(Matchers.any(), Matchers.any(), Matchers.any()) 
      .thenReturn(mock); 

     // The code that will call someMethod 
     MyOtherClass mc = new MyOtherClass(); 
     mc.someMethod(); 
    } 
} 

假設我MyClass類看起來是這樣的:

public class MyClass { 

    public static class MyStaticClass { 
     public MyStaticClass(Object arg1, Object arg2, Object arg3) { 
      System.out.println("Called constructor"); 
     } 

     public void callSomeMethod() { 
      System.out.println("callSomeMethod"); 
     } 
    } 
} 

而且我MyOtherClass類看起來是這樣的:

public class MyOtherClass { 
    public void someMethod() { 
     MyClass.MyStaticClass myStaticClassInstance = new MyClass.MyStaticClass(
      new Object(), new Object(), new Object() 
     ); 
     myStaticClassInstance.callSomeMethod(); 
    } 
} 

如果我啓動我的測試,我得到預期:

My new Answer 

相反的,我應該在默認情況下得到:

Called constructor 
callSomeMethod 

更多how to constructions of new objects細節。

+0

是的,它是明確的,但它不工作。當執行'new MyClass.MyStaticClass(arg1,arg2,arg3)'時,執行會進入靜態類的構造函數內,這就是我想要避免的。 – jerome

+0

我不是在定義它的公共類中實例化靜態類,這與您的代碼有所不同。 – jerome

+1

我用'@PrepareForTest(SomeClass .class)'更改'@PrepareForTest(MyClass.class)'並且它正在工作。感謝你的代碼示例,它幫助了我很多。 – jerome

0

您可以使用PowerMockito用的Mockito讓這件事完成。

@RunWith(PowerMockRunner.class) 
@PrepareForTest(DriverManager.class) 
public class TestMocker { 

    @Test 
    public void testName() throws Exception { 

     //given 
     PowerMockito.mockStatic(DriverManager.class); 
     BDDMockito.given(DriverManager.getConnection(...)).willReturn(...); 

     //when 
     sut.execute(); 

     //then 
     PowerMockito.verifyStatic(); 
     DriverManager.getConnection(...); 

    } 

希望這會有所幫助。快樂編碼!

0

我寫了一個簡單的工具,嘲諷的事情,在https://github.com/iirekm/misc/tree/master/ajmock

通常是 '非mockable' 你的代碼可以是這樣的:

``` 公共類MyClassTest {

@Test 
public void test() throws Exception { 
    MyClass.MyStaticClass mock = Mockito.mock(MyClass.MyStaticClass.class); 
    when(() -> mock.callSomeMethod()).thenAnswer(() -> ...); 

    when(() -> new MyClass.MyStaticClass(any(), any(), any())).thenReturn(mock); 

    // The code that will call someMethod 
    MyOtherClass mc = new MyOtherClass(); 
    mc.someMethod(); 
} 

}

```