Как я могу издеваться над переменной поля, которая инициализируется встроенной?
class Test {
private Person person = new Person();
...
public void testMethod() {
person.someMethod();
...
}
}
Здесь я хочу поиздеваться person.someMethod()
при тестировании Test.testMethod()
метода, для которого мне нужно имитировать инициализацию person
переменной. Есть подсказка?
Изменить: мне не разрешено изменять класс Person.
Person
. Варианты включают добавление конструктора для этого или добавление метода установки.Ответы:
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, которые могут быть полезны и избавят вас от втягивания еще одной библиотеки.
источник
internal
пакете и, похоже, больше не работает в Mockito 2.6.2.Довольно поздно на вечеринку, но здесь меня ударило, и мне помог друг. Дело было не в использовании 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(); }
Таким образом вы можете передать фиктивный объект, а затем проверить его позже.
Вот ссылка.
источник
FieldSetter
больше не доступен в Mockito 2.x.Class#getDeclaredField
принимает один параметр, поэтому паренсы должны выглядеть такFieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson);
. Вот почему я ошибся и подумал, что может быть хорошей идеей исправить это в вашем примере. Спасибо за ответ.Если вы используете Spring Test, попробуйте org.springframework.test.util.ReflectionTestUtils
ReflectionTestUtils.setField(testObject, "person", mockedPerson);
источник
testImplementation("org.springframework:spring-test:5.1.2.RELEASE")
Я уже нашел решение этой проблемы, которое забыл опубликовать здесь.
@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(); } }
Ключевые моменты этого решения:
Выполнение моих тестовых случаев с PowerMockRunner:
@RunWith(PowerMockRunner.class)
Попросите Powermock подготовиться
Test.class
к манипуляции с частными полями:@PrepareForTest({ Test.class })
И, наконец, смоделируйте конструктор класса Person:
PowerMockito.mockStatic(Person.class);
PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
источник
mockStatic
функции, но она не представлена в вашем примере кода. Должен ли бытьmockStatic
вызов в примере кода или это не требуется для конструкторов?Следующий код можно использовать для инициализации маппера в макете клиента REST.
mapper
Поле является частным и должно быть установлено во время установки модульного тестирования.import org.mockito.internal.util.reflection.FieldSetter; new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());
источник
Используя руководство @Jarda, вы можете определить это, если вам нужно установить для переменной одно и то же значение для всех тестов:
@Before public void setClientMapper() throws NoSuchFieldException, SecurityException{ FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper()); }
Но имейте в виду, что с установкой других частных значений следует обращаться осторожно. Если они частные, то по какой-то причине.
Например, я использую его, например, для изменения времени ожидания сна в модульных тестах. В реальных примерах я хочу спать на 10 секунд, но в модульном тесте я доволен, если это происходит немедленно. В интеграционных тестах вы должны проверить реальное значение.
источник