2013-07-30 2 views
9

Я пытаюсь проверить абстрактный класс, а Mockito не инициализирует мои переменные-члены. Вот простой пример, чтобы показать вам мою проблему.Почему Mockito пропускает инициализацию переменной-члена моего абстрактного класса

Это абстрактный класс, который инициализирует его член «поле»:

import java.util.ArrayList; 
import java.util.Collection; 

public abstract class Foo { 
    private final Collection field = new ArrayList(); 

    protected Foo() { 
     System.out.println("In constructor"); 
    } 

    public boolean isNull(Object o) { 
     field.add(o); 

     return o == null; 
    } 

    abstract void someAbstractMethod(); 
} 

Вот тестовый класс:

import org.junit.Assert; 
import org.junit.Test; 
import org.mockito.Mockito; 

public class FooTest { 
    @Test 
    public void testSomething() { 
     final Foo foo = Mockito.mock(Foo.class); 

     Mockito.when(foo.isNull(Mockito.anyObject())).thenCallRealMethod(); 

     Assert.assertFalse(foo.isNull("baaba")); 
    } 
} 

Когда тест запускается его бросает NPE, так как поле переменной» 'не инициализируется!

Что я делаю неправильно?

+0

Использование http://docs.mockito.googlecode.com/hg/org/mockito/stubbing/OngoingStubbing.html#thenCallRealMethod%28%29 не рекомендуется. Что вы хотите проверить? Если это реализация некоторых методов Foo, просто создайте подкласс. Используйте Mockito, когда вы хотите проверить поведение или вызовы метода заглушки. –

+0

Как я сказал [@ david-wallace] (http://stackoverflow.com/users/1081110/david-wallace), я хочу протестировать абстрактный класс. Мое намерение использовать макет заключалось в том, чтобы предотвратить ошибку компиляции, если изменится абстрактный класс или один из его интерфейсов. – Pigelvy

ответ

4

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

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

Попытка вызова реального метода обычно неправильна при использовании mocks. Вместо этого нужно заглушить поведение макета.

Mockito.when(foo.isNull(Mockito.anyObject())).thenReturn(false); 
Assert.assertFalse(foo.isNull("baaba")); // assertion always passing 

Я не знаю фактическое использование случая, но, возможно, вы хотите частичный макет, с spy. Хотя это по-прежнему считается плохой практикой, поскольку обычно это означает, что вам нужно реорганизовать код для использования композиции.

+0

Я ожидал, что Мокито сделает что-то, что он не предназначен. Как обсуждалось с [@ David-Wallace] (http://stackoverflow.com/users/1081110/david-wallace), я создам фиктивную реализацию в своих тестах, которые мне придется поддерживать, если методы будут добавлены/удалены. Thx – Pigelvy

+0

Является ли это ожидаемым поведением для статических элементов тоже? Я пробовал, и Mockito требовал, чтобы статические члены были инициализированы, он также должен пропустить эту инициализацию? – dushyantashu

+0

Статические элементы @dushyantashu инициализируются загрузчиком классов при загрузке класса. Мокито не меняет этого. – Brice

3

Вы, кажется, издеваетесь над классом, который вы пытаетесь протестировать. На самом деле это не идея насмешки. Вы издеваетесь над классами, которые выходят за рамки вашего теста, и оставляйте то, что вы тестируете, не сфотографированы.

В этом случае вы должны, вероятно, просто создать Foo с фиктивной реализацией someAbstractMethod и проверить это непосредственно. Насколько мне известно, не нужно насмешек.

+0

Действительно, я хочу издеваться над абстрактным классом, который я тестирую, чтобы тесты не прерывались всякий раз, когда к этому классу (или к одному из его интерфейсов) добавляется новый абстрактный метод. Неужели это плохая практика? – Pigelvy

+0

Я недостаточно опытен, чтобы изложить закон о том, что такое «плохая практика», а что нет. Но это похоже на использование долота в качестве отвертки. Это не то, над чем были рассчитаны издевательства.Мой инстинкт просто заключался бы в проверке вашей собственной фиктивной реализации и добавлении новых методов везде, где они нужны. Я полагаю, это зависит от того, как часто вы хотите добавить новый абстрактный метод в класс, - если это часто случается, то точка Брайса о рефакторинге использования композиции, вероятно, применима. Ответ на ваш вопрос заключается в том, что Mockito никогда не предназначался для ... –

+0

... инициализировать поля в своих издевательствах; теперь вооруженный этими знаниями, продолжайте и проводите ваши испытания любым способом, который вам подходит. –

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