2013-09-22 7 views
2

У меня есть класс, который является подклассом Context. Я тестирую единицы другого класса, которые имеют отношение к этому классу, и поэтому я издевался над ним. Тем не менее, мне нужны некоторые методы, чтобы действовать как их первоначальное поведение, поэтому я собираюсь «развязать» их.Mockito - переопределение метода, который принимает примитивные параметры

Один из них getAssets(), так что я написал это, и она работает правильно:

Mockito.doReturn(this.getContext().getAssets()).when(keyboard).getAssets(); 

keyboard является издевались экземпляр класса упоминается.

Поскольку этот метод не принимает параметров, переопределение его было довольно простым.

Мне также необходимо переопределить Context.getString(int). Параметр усложняет ситуацию и является примитивным, что еще более затрудняет задачу.

Я взял this advice и еще один, и попытался писать этот код:

Mockito.when(keyboard.getString(Mockito.anyInt())).thenAnswer(new Answer<String>(){ 
    @Override 
    public String answer(InvocationOnMock invocation) throws Throwable 
     Integer arg = (Integer)invocation.getArguments()[0]; 
     return OuterClass.this.getContext().getString(arg.intValue()); 
    } 
}); 

Это компилируется и выполняется, но дал следующее исключение:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers! 
0 matchers expected, 1 recorded: 
-> at [...] <The code above> 

This exception may occur if matchers are combined with raw values: 
//incorrect: 
someMethod(anyObject(), "raw String"); 
When using matchers, all arguments have to be provided by matchers. 
For example: 
//correct: 
someMethod(anyObject(), eq("String by matcher")); 

For more info see javadoc for Matchers class. 

at android.content.Context.getString(Context.java:282) 
at [...] 
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169) 
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154) 
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:545) 
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1551) 

Так что главный вопрос заключается в том, чтобы переопределить методы в Мокито, которые имеют примитивные параметры?

Заранее спасибо

+1

Я не могу воспроизвести вашу ошибку. Если вы ищете 'InvalidUseOfMatchersException', вы найдете множество связанных вопросов и ответов.Проблема в том, что вы вызываете метод Mockito с одним аргументом Matcher и без него, что запрещено по разным причинам. –

+0

Спасибо, что попробовали. Да, я уже искал и все еще делаю. – Mousa

ответ

3

Вы не можете заглушить getString, потому что это окончательный. Мокито не может заглушить окончательные методы. Просто оставьте его ненакрашенным, и вы получите его первоначальную реализацию. Это то, чего ты хочешь, да?

+1

Да, я хочу это, но оставив его как есть, результат для 'NullPointerException' внутри' getString() '! Я считаю, что это потому, что он называет другие методы, которые затушевывают. Вот почему я пытаюсь передать его с 'MockedKeyboard.getString()' на 'AndroidTestCase.getContext.getString()'. Разве это не так? – Mousa

+1

Вы можете попробовать создать макет с ответом по умолчанию 'CALLS_REAL_METHODS', а затем просто заглушить те методы, которые вы действительно хотите заглушить. Итак, 'Context mockContext = mock (Context.class, CALLS_REAL_METHODS);'. У вас могут возникнуть проблемы, если один из методов использует поле, которое не было инициализировано. –

+0

О, спасибо, человек, я искал такую ​​функцию :) Это помогает пока. – Mousa

1

Не должна ли она быть Answer<String>?

Mockito.when(keyboard.getString(Mockito.anyInt())).thenAnswer(new Answer<String>(){ 
    @Override 
    public String answer(InvocationOnMock invocation) throws Throwable { 
     return "foo"; 
    } 
}); 

И вы могли бы переименовать клавиатуру -> mockContext, это было бы более ясно?

+0

О да, спасибо, я был полностью замешан в методе 'answer()'. Я исправил его, однако, исключение одно и то же! – Mousa

+0

действительно странная ошибка, вы уверены, что нет другого притворного вызова, вызывающего эту ошибку? – Snicolas

+0

Это происходит, когда вы создаете ожиданное ожидание вызова со смешанными параметрами: как Mockito.anyXXX, так и реальный параметр (т. Е. «Foo»). – Snicolas

0

Как David Wallace, указанным в his answer, метод Context.getString() является окончательным, и мы знаем, что mockito не может высмеять окончательные методы. Так что переопределение это тоже плохая идея, и она не сработает.

"0 matchers expected, 1 recorded" информация о описании InvalidUseOfMatchersException, является смутным способом сказать, что метод final, и мы не должны пытаться его переопределить.

Однако оставить его как есть не поможет, потому что объект все еще является издеваемым объектом, и метод не покажет ожидаемое поведение, которое мы хотим от обычного объекта; поэтому этот параметр также находится вне таблицы.

Наконец-то я решил изменить и улучшить свой дизайн. Я использовал Interface segregation principle и разделил обязанности Context и Keyboard (Я разрабатываю службу IME). В самой заявке я передал один и тот же объект keyboard для этих двух, но в тесте я высмеивал Keyboard без каких-либо плохих побочных эффектов и использовал TestCase.getContext() как Context, что устранило необходимость «разблокировать» его методы.

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