2016-03-23 6 views
25

Как я могу высмеять переменную поля, которая инициализируется inline?Mockito: Mock инициализация частного поля

например.

class Test { 
    private Person person = new Person(); 
    ... 
    public void testMethod() { 
     person.someMethod(); 
     ... 
    } 
} 

Здесь я хочу издеваться person.someMethod() в то время как метод тестирования - Test # TestMethod.

, для которого мне нужно высмеять инициализацию переменной человека. Любая подсказка?

EDIT: Мне не разрешено изменять класс Person.

+0

Эта ссылка может быть полезной для вас http://stackoverflow.com/questions/13645571/how-to-mock-a-private-dao-variable – Popeye

+2

Вы должны реорганизовать кода, чтобы вы могли передать макет для 'Person'. Параметры включают добавление конструктора для этого или добавление метода сеттера. –

ответ

9

Я уже нашел решение этой проблемы, которую забыл написать здесь.

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ Test.class }) 
public class SampleTest { 

@Mock 
Person person; 

@Test 
public void testPrintName() throws Exception { 
    PowerMockito.mockStatic(Person.class); 
    PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person); 
    Test test= new Test(); 
    test.testMethod(); 
    } 
} 

Ключевых моментов для этого решения являются:

  1. Запуск моих тестовых случаев с PowerMockRunner: @RunWith(PowerMockRunner.class)

  2. проинструктировать Powermock подготовить Test.class манипуляции частных полей: @PrepareForTest({ Test.class })

  3. И, наконец, издевается над конструктором класса Person:

    PowerMockito.mockStatic(Person.class); PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);

0

Может быть много способов, один из них может быть

Class Test { 
    private Person person = new Person(); 
    ... 
    public void testMethod() { 
    person.someMethod(); 
    ... 
    } 
} 

Это должно быть изменено, как

Class Test { 
    private Person person; 
    public Test() { 
     if(person == null) { 
     person = new Person(); 
     } 
    } 
    ... 
    public void testMethod() { 
    person.someMethod(); 
    ... 
    } 

} 

В тесте на тест,

@Runwith(SpringJunit4Runner.class) 
public class TestingTest { 

@InjectMocks 
Test test; 

@Mock 
private Person person; 

@Before 
public void setUp() { 

when(person.XXX).thenReturn(""); 

} 

@Test 
public void testMethod() { 

........... 
} 
} 
+0

Я не уверен, что так будет работать, мы не можем издеваться над конструктором так, как вы это делаете. используя Powermock, мы можем это сделать. Но кроме всего этого мне не разрешено изменять класс этого человека. :( – Arun

37

Mockito поставляется с вспомогательный класс, чтобы сэкономить некоторое количество кода котла с отражателем:

import org.mockito.internal.util.reflection.Whitebox; 

//... 

@Mock 
private Person mockedPerson; 
private Test underTest; 

// ... 

@Test 
public void testMethod() { 
    Whitebox.setInternalState(underTest, "person", mockedPerson); 
    // ... 
} 

Update: К сожалению, команда Mockito решила remove the class в Mockito 2. Таким образом, вы вернулись к написанию собственного кода отражения шаблонный, использовать другую библиотеку (например, Apache Commons Lang), или просто воровать класс Whitebox (это MIT licensed).

+0

Я слежу за своим целевым объектом по другим причинам, и в этом случае, когда мой объект является шпионом, я не могу установить внутреннее состояние таким образом. – Arun

+0

Почему бы и нет? Я использую его со шпионами. Создайте экземпляр Person.Stub, что бы ни требовалось, и установите его на экземпляр Test. – Ralf

+0

Предупреждение: Whitebox находится в пакете 'internal' и, похоже, больше не работает на Mockito 2.6.2. – Nova

Смежные вопросы