Какова лучшая платформа для создания фиктивных объектов в Java? Зачем? Каковы плюсы и минусы каждой структуры?
Какова лучшая платформа для создания фиктивных объектов в Java? Зачем? Каковы плюсы и минусы каждой структуры?
Ответы:
У меня был хороший успех с использованием Mockito .
Когда я попытался узнать о JMock и EasyMock, я обнаружил, что кривая обучения немного крутая (хотя, возможно, это только я).
Мне нравится Mockito из-за его простого и понятного синтаксиса, который я смог понять довольно быстро. Минимальный синтаксис предназначен для очень эффективной поддержки общих случаев, хотя несколько раз, когда мне нужно было сделать что-то более сложное, я обнаружил, что то, что я хотел, было поддержано и легко понять.
Вот (сокращенный) пример с домашней страницы Mockito:
import static org.mockito.Mockito.*;
List mockedList = mock(List.class);
mockedList.clear();
verify(mockedList).clear();
Это не становится намного проще, чем это.
Единственный существенный недостаток, о котором я могу думать, это то, что он не будет издеваться над статическими методами.
Я создатель PowerMock, поэтому, очевидно, я должен рекомендовать это! :-)
PowerMock расширяет возможности EasyMock и Mockito, позволяя имитировать статические методы , финальные и даже частные методы. Поддержка EasyMock завершена, но плагин Mockito требует дополнительной работы. Мы также планируем добавить поддержку JMock.
PowerMock не предназначен для замены других каркасов, скорее его можно использовать в сложных ситуациях, когда другие каркасы не допускают насмешки. PowerMock также содержит другие полезные функции, такие как подавление статических инициализаторов и конструкторов.
Сайт JMockit проект содержит большое количество сравнительных данных для текущих инструментарии Mocking.
В частности, ознакомьтесь с матрицей сравнения функций , которая охватывает EasyMock, jMock, Mockito, Unitils Mock, PowerMock и, конечно, JMockit. Я стараюсь, чтобы это было максимально точным и актуальным.
У меня был успех с JMockit .
Это довольно новое и немного сырое и недостаточно документированное. Он использует ASM для динамического переопределения байт-кода класса, поэтому он может макетировать все методы, включая статические, частные, конструкторы и статические инициализаторы. Например:
import mockit.Mockit;
...
Mockit.redefineMethods(MyClassWithStaticInit.class,
MyReplacementClass.class);
...
class MyReplacementClass {
public void $init() {...} // replace default constructor
public static void $clinit{...} // replace static initializer
public static void myStatic{...} // replace static method
// etc...
}
Он имеет интерфейс Ожидания, позволяющий также сценарии записи / воспроизведения:
import mockit.Expectations;
import org.testng.annotations.Test;
public class ExpecationsTest {
private MyClass obj;
@Test
public void testFoo() {
new Expectations(true) {
MyClass c;
{
obj = c;
invokeReturning(c.getFoo("foo", false), "bas");
}
};
assert "bas".equals(obj.getFoo("foo", false));
Expectations.assertSatisfied();
}
public static class MyClass {
public String getFoo(String str, boolean bool) {
if (bool) {
return "foo";
} else {
return "bar";
}
}
}
}
Недостатком является то, что требуется Java 5/6.
Вы также можете взглянуть на тестирование с помощью Groovy. В Groovy вы можете легко смоделировать Java-интерфейсы, используя оператор «as»:
def request = [isUserInRole: { roleName -> roleName == "testRole"}] as HttpServletRequest
Помимо этой базовой функциональности Groovy предлагает гораздо больше в области насмешек, в том числе мощный MockFor
и StubFor
классы.
Я начал использовать макеты с EasyMock . Достаточно легко понять, но шаг воспроизведения был довольно раздражающим. Mockito удаляет это, а также имеет более чистый синтаксис, поскольку похоже, что удобочитаемость была одной из его основных целей. Я не могу не подчеркнуть, насколько это важно, поскольку большинство разработчиков тратят свое время на чтение и поддержку существующего кода, а не на его создание.
Еще одна приятная вещь заключается в том, что интерфейсы и классы реализации обрабатываются одинаково, в отличие от EasyMock, где вам все еще нужно помнить (и проверять), чтобы использовать расширение класса EasyMock.
Недавно я быстро взглянул на JMockit , и, хотя список функций довольно прост, я думаю, что цена этого - удобочитаемость получаемого кода и необходимость писать больше.
Для меня Mockito находится в лучшем положении: его легко писать и читать, и он справляется с большинством ситуаций, которые потребуются большинству кода. Использование Mockito с PowerMock было бы моим выбором.
Стоит учесть, что инструмент, который вы бы выбрали, если бы разрабатывал самостоятельно или в небольшой дружной команде, может оказаться не лучшим выбором для большой компании с разработчиками разного уровня квалификации. Читаемость, простота использования и простота потребуют большего внимания в последнем случае. Нет смысла в том, чтобы получить идеальную среду для насмешек, если многие люди не используют ее или не поддерживают тесты.
Мы активно используем EasyMock и EasyMock Class Extension на работе и очень довольны этим. Это в основном дает вам все, что вам нужно. Посмотрите на документацию, есть очень хороший пример, который показывает вам все функции EasyMock.
Я использовал JMock рано. Я попробовал Mockito на своем последнем проекте, и мне понравилось. Более лаконично, чище. PowerMock покрывает все потребности, которые отсутствуют в Mockito, такие как насмешка статического кода, насмешка над созданием экземпляра, насмешка над конечными классами и методами. Таким образом, у меня есть все, что мне нужно для выполнения моей работы.
Мне нравится JMock, потому что вы можете устанавливать ожидания. Это полностью отличается от проверки, был ли вызван метод, найденный в некоторых фиктивных библиотеках. Используя JMock, вы можете написать очень сложные ожидания. Посмотрите на болтовню .
Да, Mockito - это отличный фреймворк. Я использую его вместе с Hamcrest и Google Guice для настройки моих тестов.
Лучшее решение для насмешки - заставить машину выполнять всю работу с помощью автоматического тестирования на основе спецификаций. Для Java см. ScalaCheck и платформу Reductio, включенную в функциональную библиотеку Java . В автоматизированных основанных на спецификациях средах тестирования вы предоставляете спецификацию тестируемого метода (свойство об этом должно быть истинным), и среда автоматически генерирует тесты, а также фиктивные объекты.
Например, следующее свойство проверяет метод Math.sqrt, чтобы увидеть, равен ли квадратный корень любого положительного числа n в квадрате n.
val propSqrt = forAll { (n: Int) => (n >= 0) ==> scala.Math.sqrt(n*n) == n }
Когда вы звоните propSqrt.check()
, ScalaCheck генерирует сотни целых чисел и проверяет ваше свойство для каждого, также автоматически проверяя, что граничные случаи хорошо покрыты.
Несмотря на то, что ScalaCheck написан на Scala и требует компилятора Scala, с ним легко протестировать код Java. Платформа Reductio в Функциональной Java - это чистая реализация Java тех же понятий.
Mockito также предоставляет возможность создания методов-заглушек, сопоставления аргументов (например, anyInt () и anyString ()), проверки количества вызовов (times (3), atLeastOnce (), never ()) и многого другого .
Я также обнаружил, что Mockito прост и чист .
В Mockito мне не нравится то, что вы не можете использовать статические методы .
Для чего-то немного другого, вы можете использовать JRuby и Mocha, которые объединены в JtestR, для написания тестов для вашего Java-кода в выразительном и лаконичном Ruby. Есть некоторые полезные примеры насмешливо с JtestR здесь . Одним из преимуществ этого подхода является то, что издеваться над конкретными классами очень просто.
Я начал использовать mocks через JMock, но в итоге перешел на EasyMock. EasyMock был просто, проще, и предоставлял синтаксис, который был более естественным. Я не переключался с тех пор.