Недавно я прочитал статью, в которой говорилось, что фиктивные объекты часто неправильно понимают и неправильно используют. Есть ли какие-то явные насмешливые анти-паттерны, на которые я могу обратить внимание?
Недавно я прочитал статью, в которой говорилось, что фиктивные объекты часто неправильно понимают и неправильно используют. Есть ли какие-то явные насмешливые анти-паттерны, на которые я могу обратить внимание?
Ответы:
Ненавижу видеть насмешки над простыми конкретными классами. Например, возьмем следующий простой класс, который не зависит ни от чего другого:
public class Person
{
private readonly string _firstName;
private readonly string _surname;
public Person(string firstName, string surname)
{
if (String.IsNullOrEmpty(firstName))
{
throw new ArgumentException("Must have first name");
}
if (String.IsNullOrEmpty(surname))
{
throw new ArgumentException("Must have a surname");
}
_firstName = firstName;
_surname = surname;
}
public string Name
{
get
{
return _firstName + " " + _surname;
}
}
}
В любых тестах, связанных с этим классом, я бы предпочел создать настоящий экземпляр и использовать его, а не какой-нибудь интерфейс, такой как «IPerson», который использовался как поддельный и ожидание. Используя реальный тест, вы получаете более реалистичный тест (у вас есть проверка параметров и реальная реализация свойства Name). Для такого простого класса, как этот, вы не делаете свои тесты медленнее, менее детерминированными или не запутываете логику (вам вряд ли нужно знать, что Name вызывалось при тестировании какого-либо другого класса) - что является обычными причинами насмешек гася.
В качестве дополнения к этому я также видел, как люди пишут тесты, в которых макет настраивается с ожиданием, а затем макет вызывается непосредственно в тесте. Неудивительно, что испытание всегда будет проходить ... хмммм ...
Это может показаться очевидным, но: не используйте фиктивные объекты в производственном коде! Я видел более одного примера, где рабочий код зависел от характеристик определенных фиктивных объектов (например, MockHttpServletRequest
от Springframework).
На мой взгляд, это чрезмерная проверка вызова метода на макетах. Я чувствую, что это практика, применяемая несколькими модельными фреймворками, такими как EasyMock, где по умолчанию имитируется поведение по умолчанию, когда происходит дополнительный вызов метода, который не был точно указан ранее. Этот вид строгой проверки ложных методов может привести к хрупким конструкциям, где малейшие изменения в коде могут привести к сбою целого набора тестов, даже несмотря на то, что основные функции остаются прежними.
Решением этой проблемы является использование заглушек вместо макетов. Статья, которую я нашел особенно поучительной по этому вопросу, была найдена в Javadoc Mockito: http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html (см. «2. Как насчет заглушки?» ), ссылка на: http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/ .
До сих пор мне нравилось работать с Mockito, потому что он не требует такого строгого насмешливого поведения, а вместо этого использует заглушки. Он также обеспечивает проверку методов на определенных объектах вместо всего фиктивного объекта; таким образом, вы в конечном итоге проверяете только те методы, которые действительно имеют значение в вашем тестовом сценарии
Здесь и там есть несколько книг, которые я могу порекомендовать затронуть эту тему, насмешливые и общие:
Шаблоны xUnit
Искусство модульного тестирования: с примерами в .Net
Тестирование Java следующего поколения: TestNG и расширенные концепции (эта книга в основном посвящена testNG, но есть хорошая глава о насмешках)
Answer.RETURNS_SMART_NULLS
настройка для насмешек, которая помогает диагностировать это.
Я наблюдал немного анти-паттернов в моем опыте.
В противном случае мой опыт работы с издевательствами, особенно Mockito, был легким. Они сделали тесты очень простыми в написании и обслуживании. GWT-тестирование взаимодействия между представителем и представителем намного проще с макетами, чем GWTTestCase.
Я считаю, что тесты, которые используют макеты на нескольких уровнях приложения, особенно трудно расшифровать и изменить. Однако я думаю, что это было смягчено в последние годы улучшенными API фальшивых фреймворков (я использую JMock, где это удобно).
5 или 6 лет назад API, такие как EasyMock, были мощными, но очень громоздкими. Часто тестовый код, который использовал его, был на несколько порядков сложнее, чем код, который он тестировал. В то время я пытался влиять на команды, в которых я был, чтобы использовать их очень экономно и обходиться простыми мошенничествами ручной работы, которые были просто альтернативными реализациями интерфейсов специально для тестирования.
В последнее время мои сильные мнения об этом стали мягче, поскольку API-интерфейсы для проверки сделали тесты, использующие их, более читабельными. По сути, я хочу, чтобы мой код (включая тесты) мог изменяться другими разработчиками, чтобы они не чувствовали себя так, как будто отбирают множество непонятных вызовов API.