2015-07-27 5 views
4

Я пытаюсь изменить значение, возвращаемое System.currentTimeMillis(), поэтому я могу выполнять такие операции, как: записать что-то в базу данных, имитировать ожидание 5 минут, выполнить запрос на базы данных (запрос зависит от того, когда это значение записано).Robolectric 3.0: Mocking System.currentTimeMillis()

код предложенный в [это SO нить]:

ShadowSystemClock shadowClock = Robolectric.shadowOf(SystemClock.class); 
shadowClock.setCurrentTimeMillis(1424369871446); 

не компилируется, так как метод shadowOf был удален. Trying альтернативы, как:

ShadowSystemClock shadowClock = new ShadowSystemClock(); 
shadowClock.setCurrentTimeMillis(1424369871446); 

Оказывается были issues with overriding currentTimeMillis(), но эти вопросы должны быть исправлены в версии 3.0.

Я мог бы добавить PowerMock в свой проект и использовать это для этого случая, я думаю, но если это возможно с Robolectric, я бы предпочел это.

Обновление: Подойдет ближе, но может что-то упустить. Этот код:

ShadowSystemClock shadowClock = new ShadowSystemClock(); 

Log("system = " + System.currentTimeMillis() + "; shadow = " + shadowClock.currentTimeMillis() + "; time from code = " + Code.getSystemTime()); 

shadowClock.setCurrentTimeMillis(50000000L); 

Log("system = " + System.currentTimeMillis() + "; shadow = " + shadowClock.currentTimeMillis() + "; time from code = " + Code.getSystemTime()); 

Выходы это:

system = 1438212006879; shadow = 0; time from code = 1438212006894 
system = 1438212006898; shadow = 50000000; time from code = 1438212006898 

Code.getSystemTime() звонит в кодовую испытывается. Метод просто возвращает System.currentTimeMillis().

Кажется, что все может работать, если ShadowSystemClock перехватил вызовы currentTimeMillis(). Есть ли способ сделать это?

+0

Вы можете поделиться своим мнением? используя Roboeletric или PowerMock? –

ответ

-1

Вы должны использовать Shadows.shadowOf()

+0

Что-то вроде этого: Shadows.shadowOf (System.class)? Это не компилируется, потому что для этого требуется объект System, о котором я не знаю, как извлечь. – Mark

+0

На самом деле вы можете просто попробовать SystemClock.sleep() в тесте напрямую? – Bajji

+0

Мне не нужно продвигать время более чем на несколько секунд, но я бы хотел избежать замедления моих тестов, ожидая, пока время действительно продвинется. :/ – Mark

7

Во-первых, потому что SystemClock одноэлементно класс, состоящий исключительно из статических методов, нет необходимости использовать shadowOf(). shadowOf() требуется только для поиска теней объекта экземпляров. Чтобы получить доступ к теневым статическим методам SystemClock, вы просто вызываете статические методы ShadowSystemClock напрямую, и вам не нужно создавать экземпляр ShadowSystemClock с вызовом new. В вашем тестовом коде вы сможете отказаться от звонка до new и отменить shadowClock.currentTimeMillis() с помощью ShadowSystemClock.currentTimeMillis().

Во-вторых, и более непосредственное отношение к ваш вопрос относительно System.currentTimeMillis() перехвата - под Robolectric это будет происходить, но только для кода, который был инструментальными - то есть, модифицированный, как он будет загружен специальным загрузчиком классов Robolectric в. В инструментальном коде все вызовы System.currentTimeMillis() заменяются на вызовы ShadowSystemClock.currentTimeMillis(), что и есть то, что вы хотите.

Итак, чтобы ваш тест работал так, как вы хотите, вам нужно убедиться, что код, который вы тестируете, инструментарий. Robolectric не делает этого для всех классов по умолчанию - только для классов Android. К сожалению, я не в состоянии проверить это для себя в данный момент, но я считаю, что вы можете сказать Robolectric о том, как измерить ваши собственные классы приложений, указав пакет (ы) в аннотации @Config - например, если вы положите @Config(instrumentedPackages={ "my.application" }) на вашем тестовом классе или методе, а затем сообщает Robolectric об инструментах всех классов в пакете «my.application». Это, в свою очередь, вызовет вызовы System.currentTimeMillis() для перенаправления на ShadowSystemClock.currentTimeMillis(), который должен быть тем, что вы хотите.

Причина, по которой это делается по-другому, заключается в том, что, используя подход класса Ройграук, нельзя модифицировать классы в пакетах java.lang.*, поскольку они уже загружены, прежде чем вы сможете установить инструментальный загрузчик классов. Существует более долгосрочная идея попытаться сделать это по-другому в Robolectric, используя подход, подобный тому, что делает JMockit, что может обойти эту проблему. Это означало бы, что вам не придется явно использовать все классы клиентов. Однако сейчас это пирог в небе, и я не задерживаю дыхание, ожидая его - надеюсь, что вышеизложенное решит вашу ближайшую проблему.

Надеюсь, это поможет.

+0

Я попробую. Спасибо! – Mark

Смежные вопросы