Статьи

Впитывая беглость мокито

Недавно я обнаружил, что пишу код для интеграции двух разнородных платформ. Одна из этих систем основана на Java, а другая, хотя и не написана на Java, предлагает Java API. Я назову эти системы Foo и Bar соответственно. Mockito

Однако до того, как я написал строку кода, стало очевидно, что для тестирования возможного адаптера потребуется явная насмешка над более поздним системным API (то есть с Foo), поскольку все, что мне нужно было, это jar-файл, классы и методы которого давали понять они общались с живым экземпляром.

Я провел несколько циклов, чтобы увидеть, что нового в мире Java-издевательств, и мне было приятно видеть, что мой старый друг Mockito все еще активен и действительно, по-прежнему, отличный инструмент для издевательств общего назначения. Для непосвященных, Mockito — это основанная на Java фреймворк, который:

… очень вкусно. Это позволяет вам писать красивые тесты с помощью простого и понятного API. Mockito не дает вам похмелья, потому что тесты очень удобочитаемы и выдают чистые ошибки проверки.

Страница проекта Google code mockito — зачем пить?

Действительно, Mockito предлагает простой и удобный API, который позволяет точно высмеивать поведение без особых хлопот. Например, основным фасадом для взаимодействия с Bar является класс QTP котором есть такие методы, как logIn , logOut и т. Д. Вместо того, чтобы полагаться на тестируемые классы для фактического вызова этих методов, я легко могу создать фиктивные экземпляры QTP с помощью Mockito, например: :

Дразнить экземпляр QTP

1
QTP qtpThing = mock(QTP.class);

Где mock — это статически импортированный метод из org.mockito.Mockito . С помощью фиктивного экземпляра я могу затем диктовать, как я хочу, чтобы некоторые методы вели себя при условии, что я передаю этот имитированный экземпляр моим тестируемым классам .

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

Соответственно, для проверки этого взаимодействия мне нужно сделать две вещи:

  • убедитесь, что метод logIn был вызван с определенными параметрами
  • getTicket ответ действительного билета, используя метод getTicket

Более того, я также хотел бы убедиться, что сбой logIn в logIn приводит к определенному взаимодействию из кода моего адаптера. Поэтому мне нужно будет высказать и какое-то исключительное поведение.

В случае макетирования конкретного метода вы просто объединяете несколько методов; в моем случае, when и тогда thenReturn делают трюк так:

Дразнить поведение getTicket

1
when(qtpThing.getTicket()).thenReturn("test-ticket");

В приведенном выше коде, когда метод getTicket вызывается в моем фиктивном экземпляре, возвращается String «test-ticket».

Затем, чтобы гарантировать, что logIn был вызван с параметрами, полученными из входящего XML-документа, я могу использовать метод verify Mockito.

Использование проверки Mockito для обеспечения правильного взаимодействия

1
verify(qtpThing, times(1)).logIn("some_value", "some_user_name", "password");

В этом случае метод logIn проверяет, что logIn вызывается один раз, и что передаются три конкретных значения String . Если эти ожидания не будут выполнены, Mockito сгенерирует исключение (и ваш соответствующий тестовый пример потерпит неудачу).

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

Контрольный пример JUnit для проверки поведения входа

01
02
03
04
05
06
07
08
09
10
11
12
@Test
public void testLoginRequest() throws Exception {
  QTP qtpThing = mock(QTP.class);
  when(qtpThing.getTicket()).thenReturn("test-ticket");
  AdapterRequest request = new AdapterRequest(XML.read("etc/test-login-req.xml"));
  QbosAdapter adapter = new QbosAdapter();
  adapter.setQtpInstance(qtpThing);
  AdapterResponse adapterResponse = adapter.performAction(request);
  assertNotNull(adapterResponse);
  verify(qtpThing, times(1)).logIn("some_value", "some_user_name", "password");
  assertEquals("test-ticket", adapterResponse.getData().getText());
}

Что если мне нужно смоделировать исключение, генерируемое объектом QTP , якобы из недопустимого параметра или неверных учетных данных во время входа в систему? Опять же, свободный API Mockito делает это бризом.

В моем случае я бы хотел, logIn метод logIn выбрасывал один из проверенных методов в сигнатуре его метода с именем UnknownQtpException . Вы можете сделать это с помощью методов doThrow и when .

Макетирование исключений в Мокито

1
doThrow(new UnknownQtpException()).when(qtpThing).logIn("", "blah", "blah");

В приведенном выше коде я явно logIn что если первый параметр команды logIn пуст, то мой QTP экземпляр QTP должен UnknownQtpException . Собрав все вместе, получим следующий тестовый пример:

Тестирование исключительных обстоятельств с JUnit & Mockito

01
02
03
04
05
06
07
08
09
10
11
12
13
@Test
public void testFailureLoginRequest() throws Exception {
  QTP qtpThing = mock(QTP.class);
  doThrow(new UnknownQtpException()).when(qtpThing).logIn("", "blah", "blah");
  XML xml = XML.read("etc/test-login-req-err.xml");
  AdapterRequest request = new AdapterRequest(xml);
  QbosAdapter adapter = new QbosAdapter();
  adapter.setQtpInstance(qtpThing);
  AdapterResponse adapterResponse = adapter.performAction(request);
  assertNotNull(adapterResponse);
  verify(qtpThing, times(1)).logIn("", "blah", "blah");
  assertEquals("FAILURE", adapterResponse.getData().getText());
}

Прелесть, конечно же, состоит в том, что мои тесты эффективно тестируют мой код адаптера, не полагаясь на стороннюю систему (в данном случае Bar). Это, естественно, проверенная временем техника тестирования, которую можно использовать на любом языке, с достойной насмешки!

Если вы обнаружите, что пишете код интеграции на Java, то я не могу рекомендовать Mockito. API Mockito довольно прост и облегчает понимание тестов. Я имею в виду, что тесты легко усваиваются. Копать это?

Ссылка: впитывание беглости Mockito от нашего партнера JCG Эндрю Гловера в блоге The Disco Blog .