Позвольте мне сначала начать с перефразирования вашего вопроса полностью рабочим кодом.
@RunWith(PowerMockRunner.class)
@PrepareForTest(Employee.class)
public class TestRunner {
@Test
public void test() throws Exception {
AppraisalCalculator acMock = PowerMockito.mock(AppraisalCalculator.class);
PowerMockito
.whenNew(AppraisalCalculator.class)
.withNoArguments()
.thenReturn(acMock);
when(acMock.appraisal()).thenReturn(600);
Employee emp = new Employee();
int actualValue = emp.updateSalary();
int expectedValue = 600;
assertEquals(expectedValue, actualValue);
}
}
Затем PowerMock работает так, что PowerMockRunner
будет смотреть на каждый класс, который необходимо подготовить (здесь Employee
), затем найдите вызов конструктора, который мы хотим заменить, и сделайте это.Это делается при загрузке класса.Байт-код реального класса, вызывающий конструктор, заменяется на тот, который возвращает макет.
Дело в том, что если вы используете отражение, PowerMock не может узнать, прочитав байт-код, что этот конструктор будет вызван.Это будет известно только динамически после этого.Так что никакой насмешки не делается.
Если вам действительно нужно создать класс, который будет смоделирован отражением, я бы на самом деле немного изменил код.
В Employee
Я бы добавил что-то вроде
protected AppraisalCalculator getCalculator() {
try {
return AppraisalCalculator.class.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
while - это метод, предназначенный для выделения конструкции калькулятора.
, просто создайте дочерний класс
@Test
public void testWithChildClass() {
// Note that you don't need PowerMock anymore
AppraisalCalculator acMock = Mockito.mock(AppraisalCalculator.class);
when(acMock.appraisal()).thenReturn(600);
Employee emp = new Employee() {
@Override
protected AppraisalCalculator getCalculator() {
return acMock;
}
};
int actualValue = emp.updateSalary();
int expectedValue = 600;
assertEquals(expectedValue, actualValue);
}
или частичный макет (шпион)
@Test
public void test2() {
// No PowerMock either here
AppraisalCalculator acMock = Mockito.mock(AppraisalCalculator.class);
when(acMock.appraisal()).thenReturn(600);
Employee emp = spy(new Employee());
doReturn(acMock).when(emp).getCalculator();
int actualValue = emp.updateSalary();
int expectedValue = 600;
assertEquals(expectedValue, actualValue);
}