Мокито - ощущение, что я не использую весь свой потенциал - PullRequest
6 голосов
/ 22 февраля 2012

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

У меня есть класс с зависимостями:

public class C {
    public C (A a, B b) {
        this.a = a;
        this.b = b;
    }

    public String fooBar() {
        return a.foo() + b.bar();
    }
}

В моем тестовом классеЯ смоделирую эти зависимости и сообщу им, какие значения возвращать при вызове некоторых указанных методов:

public class CSpec {
    private A a = mock(A.class);
    private B b = mock(B.class);

    @Test
    public itShouldReturnFooBar() {
        when(a.foo()).thenReturn("foo");
        when(b.bar()).thenReturn("bar");

        C c = new C(a, b);

        assertThat(c.fooBar().isEqualTo("foobar"));
    }
}

(надеюсь, этот пример не слишком простой или слишком производный ;-)).Это отлично работает, это позволяет мне тестировать классы (здесь: C) в изоляции.Тем не менее, я никогда не использую методы verify Mockito или любые другие его функции.Хорошо ли / достаточно ли использовать Mockito таким образом?

Ответы [ 5 ]

5 голосов
/ 22 февраля 2012

Проверка обычно используется для проверки того, что ваш C действительно вызывает методы A.foo () и B.bar ().Таким образом, вы можете добавить

verify(a).foo();
verify(b).foo();

до или после assertThat.Я не думаю, что вы нуждаетесь или должны использовать их здесь, но есть несколько ситуаций, когда вам нужно это:

  • a или b делает что-то, что не видно / недоступно из публичного API c (например,ведение журнала)
  • Вас интересует порядок выполнения
  • Вы хотите убедиться, что вызываются методы only a.foo и b.bar, больше ничего не похоже на a.foo2
  • Вы можете использовать эти шутки в качестве шпиона, так что вызов на a.foo будет затем направляться на aReal.foo
2 голосов
/ 23 февраля 2012

Подход verify особенно полезен в стиле программирования Tell Not Ask .

Рассмотрим следующую версию вашего класса C:

public class C {
  public C(A a, B b, CListener L) { ... }
  ...
  public void foobar() {
    String result = complexPrivateMethod(a, b);
    L.fooBarred(result);
  }
}

Таким образом, вместо того, чтобы просто вычислять результат, вы информируете некоторую заинтересованную сторону (например, пользовательский интерфейс) о результате.

Чтобы проверить foobar сейчас, вам нужно убедиться, что слушатель правильно вызван:

public class CTest {
   @Mock CListener mockListener;
   ...

   @Test itShouldTellCAboutFooBar() {
      C c = new C(stubbedA, stubbedB, mockedListener);
      ...
      verify(mockedListener).fooBarred("foobar");
   }  
}

Это использование verify типично для разработки через тестирование: см. Freeman & Pryce's Growing Object-Oriented Software, управляемый тестами .

Таким образом, если вы хотите использовать весь потенциал Mockito (вопрос), вам больше всего нужно принять соответствующую философию дизайна в вашем коде.

1 голос
/ 23 февраля 2012

Ответы, данные до сих пор, хороши, но есть и дополнительные функции, о которых вы тоже не упомянули.Аннотации @Mock, @Spy, @InjectMocks очень полезны.Наряду с методами verify(...) существует также класс InOrder, помогающий проверить порядок вызовов методов.Возможно, вы уже используете методы сопоставления (<T> any(T t), anyString() и т. Д.), Но не показываете, что используете эти возможности.

1 голос
/ 22 февраля 2012

Совершенно нормально использовать Mockito именно таким образом.Но если ваш код становится более сложным, вам нужно сделать еще кое-что, чтобы его тестирование было как можно более простым.

Еще один небольшой пример:

public void eitherAorB() {
    if(somethingIsTrue) {
        a.doSomething();
    } else {
        b.doSomethingElse();
    }
}

Возможно, вы захотите убедиться,что ожидаемый метод вызывается для ожидаемого объекта.

@Test
public doSomethingShouldBeCalledOnA() {
    A a = mock(A.class);
    C c = new C(a, new B());

    c.setSomeThingIsTrue(true);
    eitherAorB();

    verify(a).doSomething();
}

@Test
public doSomethingElseShouldBeCalledOnB() {
    B b = mock(B.class);
    C c = new C(new A(), b);

    c.setSomeThingIsTrue(false);
    eitherAorB();

    verify(b).doSomethingElse();
}

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

Или, в некоторых случаях, вам нужно вызвать реальный метод или использовать реальный объект (без подделок), так что пришло время шпионить за объектом и захватывать аргументы или проверять поведение.

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

1 голос
/ 22 февраля 2012

Да, с этим тестом проблем нет, все отлично.Тот простой факт, что используются заглушки, заставляет тест работать, если вы удалите или измените заглушки, то тест не будет работать.

Добавление операторов проверки просто сделает вещи лишними в таких тестах.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...