Я использую JMockit для моделирования System.currentMillis().
Немногие призывы возвращают насмешливое время, но через какое-то время он начинает возвращаться к исходному времени.
Когда я запускаю то же самое после отключения JIT, он работает отлично.JMockit: Издевательство над apis возвращаются после somtime
ответ
Это происходит потому, что оптимизатор JIT в JVM не проверяет переопределенные методы (переопределение выполняется через другую подсистему в JVM). Таким образом, в конечном итоге JVM решает оптимизировать код, содержащий вызов, System.currentTimeMillis()
, вставляя вызов метода Java native
, чтобы он сразу начал выполнять фактический собственный метод. На этом этапе оптимизатор должен проверить, переопределено ли сейчас currentTimeMillis()
или нет, и отказаться от вложения в случае его переопределения. Но, к сожалению, инженеры JDK не смогли объяснить эту возможность.
Если вам действительно нужно вызывать издеваемое System.currentTimeMillis()
слишком много раз, единственное обходное решение действительно должно работать с -Xint
(что не так уж плохо, поскольку обычно это сокращает общее время выполнения тестового прогона).
Очевидно, что у вас есть важная зависимость от текущего времени внутри одного или нескольких компонентов. В этом случае вы должны выразить эту зависимость с интерфейсом:
public interface TimeService {
long currentTimeMillis();
}
В вашем реальном коде у вас есть реализация, которая использует System
метод:
public final SystemTimeService implements TimeService {
@Override
public long currentTimeMillis() {
return System.currentTimeMillis();
}
}
Note, с Java 8 вы можете уменьшить код чтобы выразить это более ясно (спасибо @Holger):
public interface TimeService {
static final DEFAULT = System::currentTimeMillis;
long currentTimeMillis();
}
Ваши классы, которые зависят от этого времени службы должен выглядеть так:
public final ClassThatDependsOnTimeService {
private final TimeService timeService;
public ClassThatDependsOnTimeService(TimeService timeService) {
this.timeService = timeService;
}
// other features omitted
}
Теперь они могут быть поданы с
TimeService timeService = new SystemTimeService();
ClassThatDependsOnTimeService someObject = new ClassThatDependsOnTimeService(timeService);
или (Java 8):
ClassThatDependsOnTimeService someObject = new ClassThatDependsOnTimeService(TimeService.DEFAULT);
или с какой-либо рамки инъекции зависимостей или любой другой.
В ваших тестах вы не издеваетесь над методом System.currentTimeMillis
, но вы издеваетесь над интерфейсом TimeService
и вводите макет в зависимости от классов.
Это хороший совет. В Java 8 вы также можете добавить 'TimeService DEFAULT = System :: currentTimeMillis;' в 'interface', уменьшая код, необходимый для абстракции. – Holger
- 1. Издевательство над списком объектов
- 2. Повторное издевательство над испытаниями
- 3. Издевательство над классом
- 4. Рекурсивное издевательство над Rhino-Mocks
- 5. Издевательство над контроллером на CakePHP
- 6. Издевательство над классом в PowerMock
- 7. Издевательство над моделью Entity Framework?
- 8. Издевательство над оператором в Moq
- 9. Moq: Издевательство над классом с множественным наследованием
- 10. Как сделать издевательство над финальным классом?
- 11. Издевательство над классом бетона с помощью EasyMock
- 12. Издевательство над классом внутри тестируемого метода
- 13. HippoMocks - издевательство над функцией, которая возвращает unique_ptr
- 14. Почему не происходит следующее издевательство над Ninject.Moq?
- 15. Издевательство над NSubstitute, нуждается в некоторой ясности.
- 16. Издевательство над классом и издевательством его интерфейса
- 17. Rspec - издевательство над методом в другом классе
- 18. Как создать «глубокое» издевательство над фасолью?
- 19. Издевательство над чертой с scala-mock
- 20. Как издеваться над InetAddress.getLocalHost() с помощью JMockit
- 21. Как издеваться над методом в JMockit?
- 22. JMockit: Как издеваться над защищенными методами?
- 23. Как издеваться над созданием в jmockit
- 24. Как издеваться над классом InitialContext с jmockit?
- 25. Не могу издеваться над EntityManager jMockit
- 26. Издевательство с использованием FileStream
- 27. Издевательство над методом, возвращающим generics с подстановочным знаком, используя mockito
- 28. clojure: элегантное издевательство над функциями с различными значениями
- 29. Издевательство над классом с явно реализованным интерфейсом с использованием Foq
- 30. Издевательство над классом, который наследуется от другого класса
Интересно. Является ли он специфичным для currentTimeMillis()? В противном случае весь Инструментарий пойдет на бросок, и это будет вероятностная функция. @Rogerio –
Он влияет только на собственные методы, такие как 'currentTimeMillis()'. –
Я не удивлюсь, если это применимо ко всем [* внутренним * методам] (https://wikis.oracle.com/display/HotSpotInternals/PerformanceTechniques#PerformanceTechniques-Intrinsics), независимо от того, есть ли у них «родной» или чистой реализации Java. Ожидается, что эти методы будут иметь четко определенную семантику. Например. 'Math.sqrt' не является« родным », но я думаю, что издевательство над ним не удастся, как только оптимизатор начнет работать ... – Holger