2017-01-23 8 views
2

У меня есть метод в классе, который создает экземпляр статического класса и операцию вызова на нем.Mocking static class

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() { 
     } 
    } 
} 

Как издевается статический класс при создании экземпляра, так что я мог издеваться callSomeMethod() без прохождения через конструктор статического класса?

+0

лет u не должен создавать экземпляр 'MyStaticClass' в' SomeClass' вообще в первую очередь. Вы должны использовать * инверсию зависимостей *, чтобы вставлять экземпляры '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

Да, это ясно, но оно не работает. Выполнение выполняется внутри конструктора статического класса при выполнении нового MyClass.MyStaticClass (arg1, arg2, arg3); это то, чего я хочу избежать. – jerome

+0

Я не инициирую статический класс внутри открытого класса, где он определен, то есть разница с вашим кодом. – jerome

+1

Я изменяю '@PrepareForTest (MyClass.class)' с '@PrepareForTest (SomeClass .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

Я написал простой инструмент для насмешливый вещей, которые обычно 'не mockable' на https://github.com/iirekm/misc/tree/master/ajmock

Ваш код может выглядеть следующим образом:

`` ` общественного класса 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(); 
} 

}

`` `