Подтвердить что ты не робот

Mockito: Мощная инициализация частного поля

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

например.

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

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

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

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

4b9b3361

Ответ 1

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

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

@Mock
Person person;

@Test
public void testPrintName() throws Exception {
    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);

Ответ 2

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

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

//...

@Mock
private Person mockedPerson;
private Test underTest;

// ...

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

Обновление: К сожалению, команда mockito решила удалить класс в Mockito 2. Итак, вы вернулись к написанию своего собственного стандартного кода отражения, использовали другую библиотеку (например, Apache Commons Lang) или просто украли класс Whitebox (он лицензирован MIT).

Обновление 2: JUnit 5 поставляется с собственными классами ReflectionSupport и AnnotationSupport, которые могут быть полезны и избавят вас от использования еще одной библиотеки.

Ответ 3

Довольно поздно на вечеринку, но я был поражен здесь и получил помощь от друга. Дело не в том, чтобы использовать PowerMock. Это работает с последней версией Mockito.

Mockito поставляется с этим org.mockito.internal.util.reflection.FieldSetter.

То, что он в основном делает, это помогает вам модифицировать приватные поля, используя отражение.

Вот как вы используете это -

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson);
    // ...
    verify(mockedPerson).someMethod();

}

Таким образом, вы можете передать фиктивный объект, а затем проверить его позже.

Ссылка:

https://www.codota.com/code/java/methods/org.mockito.internal.util.reflection.FieldSetter/set

Ответ 4

Если вы используете Spring Test, попробуйте org.springframework.test.util.ReflectionTestUtils

 ReflectionTestUtils.setField(testObject, "person", mockedPerson);

Ответ 5

Следующий код может быть использован для инициализации mapper в макете клиента REST. Поле mapper является частным и должно быть установлено во время настройки модульного теста.

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

new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());

Ответ 6

Используя руководство @Jarda, вы можете определить это, если вам нужно задать для переменной одинаковое значение для всех тестов:

@Before
public void setClientMapper() throws NoSuchFieldException, SecurityException{
    FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper());
}

Но имейте в виду, что с настройкой частных значений следует обращаться с осторожностью. Если они частные, по какой-то причине.

Например, я использую его, например, для изменения времени ожидания сна в модульных тестах. В реальных примерах я хочу спать 10 секунд, но в модульном тесте я удовлетворен, если это немедленно. В интеграционных тестах вы должны проверить реальную стоимость.

Ответ 7

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

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();
    ...
  }

}

В тесте Test,

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

...........
}
}