Mockito: Мощная инициализация частного поля
Как я могу высмеять переменную поля, которая инициализируется inline?
например.
class Test {
private Person person = new Person();
...
public void testMethod() {
person.someMethod();
...
}
}
Здесь я хочу высмеять person.someMethod() во время тестирования - Test # testMethod.
для которого мне нужно высмеять инициализацию переменной человека. Любая подсказка?
EDIT: мне не разрешено изменять класс Person.
Ответы
Ответ 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();
}
}
Ключевые моменты к этому решению:
-
Запуск моих тестовых примеров с PowerMockRunner: @RunWith(PowerMockRunner.class)
-
Поручить Powermock подготовить Test.class
для работы с приватными полями: @PrepareForTest({ Test.class })
-
И, наконец, насмехайтесь над конструктором класса 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() {
...........
}
}