У меня есть два класса, чтобы попытаться выяснить, как работает whenNew
.Как powermockito перехватывает новый экземпляр?
public class RockService {
public RockData serv() {
RockData rockData = new RockData();
rockData.setName("RockService");
rockData.setContent("content from rock service");
return rockData;
} }
И
public class RockData {
String name;
long id;
String content;
// get set method ignored
}
С тестового кода
@RunWith(PowerMockRunner.class)
@PrepareForTest(RockService.class)
public class MockNewInstanceCreation {
@Test
public void mockCreationTest() throws Exception {
RockData rockData = mock(RockData.class);
when(rockData.getName()).thenReturn("this is mock");
whenNew(RockData.class).withNoArguments().thenReturn(rockData);
RockService rockService = new RockService();
RockData servData = rockService.serv();
System.out.println(servData.getName());
System.out.println(servData.getContent());
}
}
Так во время выполнения, если не издеваться, выход (RockData's getName())
будет "RockService". Но с манерой, он возвращает «это макет». Код работает, но я еще не знал, как именно это сделал Powermock/Mockito.
Я отладил код. Что меня смутило после того, как выполнено RockData rockData = new RockData();
, то, что фактически создано, является именно экземпляром, созданным RockData rockData = mock(RockData.class);
. Это означает, что new RockData()
не создает новый экземпляр вообще. Он просто вернул экземпляр, который уже был создан. И когда отладка, она подскочила до MockGateway.newInstanceCall
.
Так как же Powermockito перехватывает новый экземпляр?
я могу получить класс загрузчика часть. Mock framework будет использовать генератор байтов и загрузчик классов для издевательства над целевым классом. В моем случае это RockData. Меня смутил код, в котором был создан экземпляр. Здесь, в моем случае, RockService. В RockService.serv «RockData rockData = new RockData();» создаст новый экземпляр. Как это может быть тот же случай, что и RockData rockData = mock (RockData.class); "? Моккито взломал «новую» операцию? И вернуть существующий экземпляр вместо его создания? Как String.intern()? Или mockito также модифицирует байт-код RockService? – DeepNightTwo
Как нужно добавить @PrepareForTest (RockService.class), чтобы запустить case, а не @PrepareForTest (RockData.class). Итак, для чего нужен @PrepareForTest? – DeepNightTwo
PowerMockito не модифицирует байт-код RockService. @PrepareForTest (RockService.class) сообщает Mockito, что он должен использовать «взломанный» загрузчик классов внутри класса RockService. Без этой аннотации он будет использовать стандартный загрузчик класса java, чтобы он не смог вернуть макет RockData. . (RockData.class при нахождении уникальных) .withNoArguments() thenReturn (rockData); говорит Mockito, чтобы подготовить специальный загрузчик классов, и аннотирование PrepareForTest сообщает, где он должен использовать это, –