Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Новый проект, Когда начинаешь новый проект 
:(
    Опции темы
Shaggie
Дата 24.10.2007, 08:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 570
Регистрация: 21.12.2006
Где: outer space

Репутация: 4
Всего: 72



Цитата(nornad @ 23.10.2007,  21:14)
Цитата(Shaggie @  23.10.2007,  16:52 Найти цитируемый пост)
Так... а JMock или альтернативными вы как активно пользуетесь?

Лично я даже не слышал о таком. Я и юнит-тестами мало пользуюсь. Потому как интерфейс ими вообще не проверишь, а писать мне больше приходится интерфейсного, чем расчётного. В последних моих программах доля расчётов, которые можно обложить тестами составляет процентов десять. Имхо, юнит-тесты в этом случае уже не так полезны. Хотя в критических местах (где есть сложности с расчётами) применить всё же можно и зачастую нужно.

Вот о том и речь... Mock - болванка, заглушка. Позволяет внутри unit теста очень быстро написать реализацию интерфейса (или класса) с требуемым тебе поведением. JMock полностью совместим с JUnit и дополняет его.

Пример использования.

Предположим, что у нас есть интерфейс ICollaborator с описанием единственного метода executeJob, возвращающего строковое значение:
Код

public interface ICollaborator {
    public abstract String executeJob();
}

И есть класс ServiceClass с единственным методом runService. В качестве аргумента метод принимает реализацию интерфейса ICollaborator и сравнивает возвращаемое методом executeJob строковое значение со строкой "success". В случае совпадения значений возвращается истина, иначе - ложь.
Код

public class ServiceClass {
    public boolean runService(ICollaborator collaborator) {
        if ("success".equals(collaborator.executeJob())) {
            return true;
        }
        else {
            return false;
        }
    }
}

Что делать, если нам необходимо протестировать класс ServiceClass, но при этом писать реализацию интерфейса ICollaborator рано? Вот в таком случае нам может пригодиться JMock.

Создадим тестовый класс, и перво-наперво надо с помощью аннотации org.junit.runner.RunWith указать, что тест будет запускаться с помощью класса JMock, полностью совместимого с JUnit4.
Код

import junit.framework.TestCase;
import org.junit.runner.RunWith;
import org.jmock.integration.junit4.JMock;

@RunWith(JMock.class)
public class ServiceClassTest extends TestCase {
    ...
}

Затем нужно создать фабрику - объект Mockery. Следующим этапом будет создание болванки, являющейся "как бы" реализацией интерфейса ICollaborator.
Код

    ...
    private Mockery mockery;
    private ICollaborator collaborator;

    @Test public void testRunService() {

        mockery = new JUnit4Mockery();
        collaborator = mockery.mock(ICollaborator.class);
        ....
    }
    ...

Далее необходимо настроить поведение болванки. Сначала дам код, потом только прокомментирую его
Код

        ...
        mockery.checking(new Expectations() {{
            one(collaborator).executeJob(); will(returnValue("success"));
            one(collaborator).executeJob(); will(returnValue("failure"));
        }});
        ...

Тут с непривычки можно рехнуться, если честно! Явадок на JMock подробными комментариями не радует, поэтому за консультацией отправляю на сайт www.jmock.org, где можно найти достаточно информации по синтаксису Expectations (ожиданий). Кстати, синтаксис "ожиданий" очень похож на конструкции языка программирования Perl, такое вот ИМХО...

Метод checking навешивает на болванки требуемые нами expectations - удачное, кстати, слово. Ожидания - это то поведение, которое мы ожидаем от новоиспечённых болванок.

Метод one() принимает объект - болванку и возвращает его (объекта) как бы настоящий класс, чьи методы теперь можно вызывать, чем мы и воспользуемся. Мы "ожидаем", что будет вызван метод executeJob(). Потом метод должен (will) вернуть (returnValue) строку "success". One() подразумевает, что метод executeJob будет вызван в ходе теста ровно один раз, не больше и не меньше.

Далее код повторяется с той лишь разницей, что возвращаемым значением будет строка "failure". Для чистоты эксперимента, так сказать.

Теперь болванку collaborator можно с чистой совестью применять в данном тесте. Ограничения - должно быть ровно два вызова executeJob(), они будут возвращать разные значения. Ограничения можно сделать и не такими жёсткими, возможности работы с JMock на самом деле очень велики, охватить все его возможности в одной статье не представляется возможным. Главное - понять предназначение библиотеки и её основные концепции, а там уже можно накручивать любые конструкции ожиданий, какие только представить можно!

Ну что, тест!
Код

import junit.framework.TestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;


@RunWith(JMock.class)
public class ServiceClassTest extends TestCase {
    private ServiceClass serviceClass;
    private Mockery mockery;
    private ICollaborator collaborator;

    @Test public void testRunService() {

        mockery = new JUnit4Mockery();

        collaborator = mockery.mock(ICollaborator.class);
        
        mockery.checking(new Expectations() {{
            one(collaborator).executeJob(); will(returnValue("success"));
            one(collaborator).executeJob(); will(returnValue("failure"));
        }});

        serviceClass = new ServiceClass();

        // первый вызов - сравнение "success" и "success" вернёт истину
        boolean result = serviceClass.runService(collaborator);
        assertTrue(result);

        // второй вызов - сравнение "success" и "failire" вернёт ложь
        // конечно, два ассерта в одном тесте это непорядок. Просто для полноты картинки.
        result = serviceClass.runService(collaborator);
        assertFalse(result);
    }
}

Зелёная полоска - успех! Класс ServiceClass отработает с классами, реализующими интерфейс ICollaborator, именно так, как было задумано.

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

Пример теста взят с сайта www.ibm.com. Статья изрядно устарела - потребовалось немало поскрипеть мозгом, чтобы привести выложенный там код в рабочее состояние. Плюс ко всему, JMock уже позволяет тестировать реализации классов, не имеющих конструкторов с пустыми аргументами. Так что особой надобности в RMock, также описанном в статье, я не рассмотрел.

Вроде много написал... на ФАК, кажется, не тянет, хотя это на усмотрение модераторов.


--------------------
Цитата(alina3000 @  6.3.2014,  10:47 Найти цитируемый пост)
Сорри что не по теме 
PM MAIL ICQ GTalk Jabber   Вверх
nornad
Дата 24.10.2007, 10:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1079
Регистрация: 16.2.2007
Где: в Караганде

Репутация: 16
Всего: 31



Цитата(Shaggie @  24.10.2007,  11:03 Найти цитируемый пост)
Вот о том и речь... Mock - болванка, заглушка. Позволяет внутри unit теста очень быстро написать реализацию интерфейса (или класса) с требуемым тебе поведением

Под интерфейсом я имел в виду гуй. smile


--------------------
Три достоинства программиста: Леность, Нетерпение и Гордость
Ларри Уолл
PM MAIL WWW ICQ Skype MSN   Вверх
Shaggie
Дата 24.10.2007, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 570
Регистрация: 21.12.2006
Где: outer space

Репутация: 4
Всего: 72



Это я не догнал... smile 

Гуй тестить тяжко, согласен.


--------------------
Цитата(alina3000 @  6.3.2014,  10:47 Найти цитируемый пост)
Сорри что не по теме 
PM MAIL ICQ GTalk Jabber   Вверх
Страницы: (3) Все 1 2 [3] 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0572 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.