Использование насмешек в тестах

Существует два подхода: использование интернет-сервиса и использование некоторого локального списка (возможно, обернутый в библиотеку). То, что Вы хотите, будет зависеть от того, что Вы создаете.

Для сервисов:

Для списков:

7
задан notnoop 19 November 2009 в 18:08
поделиться

8 ответов

Это обычная проблема при имитационном тестировании, и общая мантра, чтобы избежать этого:

Только имитируйте типы, которыми вы владеете .

Здесь, если вы хотите имитировать совместную работу с анализатором XML (не обязательно, честно говоря, поскольку небольшой тестовый XML должен отлично работать в контексте модуля), тогда этот анализатор XML должен находиться за интерфейс или класс, которым вы владеете, который будет иметь дело с беспорядочными деталями того, какой метод стороннего API необходимо вызвать. Суть в том, что у него есть метод, который получает атрибут от элемента. Насмехайтесь над этим методом. Это отделяет реализацию от дизайна. Реальная реализация будет иметь реальный модульный тест, который на самом деле проверяет, получаете ли вы успешный элемент из реального объекта.

Моки могут быть хорошим способом сохранить шаблонный установочный код (действующий по сути как заглушки), но это не их основная цель с точки зрения разработки дизайна. Моки - это тестирование поведения (в отличие от состояния), и они не являются заглушками .

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

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

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

6
ответ дан 7 December 2019 в 07:46
поделиться

При разработке модульных тестов вы всегда будете эффективно тестировать свою реализацию, а не какую-то абстрактную спецификацию. Или можно возразить, что вы будете тестировать «техническую спецификацию», которая представляет собой бизнес-спецификацию, дополненную техническими деталями. В этом нет ничего плохого. Вместо проверки того, что:

Мой метод вернет значение, если определено, или значение по умолчанию.

вы тестируете:

Мой метод вернет значение, если определено, или значение по умолчанию, при условии, что предоставленный элемент xml вернет это атрибут, когда я вызываю getAttribute (name).

1
ответ дан 7 December 2019 в 07:46
поделиться

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

0
ответ дан 7 December 2019 в 07:46
поделиться

Здесь вы эффективно тестируете свой фиктивный объект. Если вы хотите протестировать метод attributeWithDefault () , вы должны подтвердить, что e.getAttribute () вызывается с ожидаемым аргументом, и забыть о возвращаемом значении. Это возвращаемое значение только проверяет настройку вашего фиктивного объекта. (Я не знаю, как именно это делается с помощью Java mockito, я чистый C # парень ...)

0
ответ дан 7 December 2019 в 07:46
поделиться

Это зависит от того, является ли получение атрибута через вызов getAttribute () частью спецификации или это деталь реализации, которая может измениться.

Если Element является интерфейсом, то утверждение, что вы должны использовать getAttribute для получения атрибута, вероятно, является частью интерфейса. Итак, ваш тест в порядке.

Если Element - конкретный класс, но attributeWithDefault не должен знать, как вы можете получить атрибут, то, возможно, здесь есть интерфейс, ожидающий появления здесь.

public interface AttributeProvider {
   // Might return null
   public String getAttribute(String name); 
}

public class Element implements AttributeProvider {
   public String getAttribute(String name) {
      return getAttributeHolder().doSomethingReallyTricky().toString();
   }
}

public class Whatever {
  public String attributeWithDefault(AttributeProvider p, String name, String default) {
     String res = p.getAtribute(name);
     if (res == null) {
       return default;
     }
   }
}

Затем вы должны протестировать attributeWithDefault против Mock AttributeProvider вместо Element.

Конечно, в этой ситуации это, вероятно, было бы излишним, и ваш тест, вероятно, просто хорош даже с реализацией (вам все равно придется где-то тестировать;)). Однако такая развязка может быть полезна, если логика когда-либо усложняется, либо в getAttribute, либо в attributeWithDefualt.

Надеюсь, это поможет.

0
ответ дан 7 December 2019 в 07:46
поделиться

Единственное решение, которое я вижу для вас здесь (и должен признать, что не знаком с используемой вами библиотекой), - это создать фиктивный элемент, обладающий всеми функциональными возможностями. включены, то есть также имеют возможность устанавливать значение getAttributeNote (). getValue () и getAttributes (). getNamedItem (). getNodeValue ().

Но, если все они эквивалентны, можно просто тестовый. Когда все меняется, вам нужно проверить все случаи.

0
ответ дан 7 December 2019 в 07:46
поделиться

Мне кажется, что есть 3 вещи, которые вы хотите проверить с помощью этого метода:

  1. Он получает атрибут из нужного места (Element.getAttribute ())
  2. Если атрибут не равен нулю, он возвращается
  3. Если атрибут равен нулю, возвращается строка «default»

В настоящее время вы проверяете # 2 и # 3, но не # 1. С помощью mockito вы можете проверить №1, добавив

verify(e.getAttribute("attribute"));
verify(e.getAttribute("other"));

, который гарантирует, что методы действительно вызываются в вашем макете. По общему признанию, это немного неуклюже в mockito. В easymock вы бы сделали что-то вроде:

expect(e.getAttribute("attribute")).andReturn("what");
expect(e.getAttribute("default")).andReturn(null);

Это имеет тот же эффект, но я думаю, что ваш тест будет немного легче читать.

0
ответ дан 7 December 2019 в 07:46
поделиться

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

Итог: если у вас есть соавтор, которого вы создаете новичком, а не внедряете, то вам, вероятно, нужно реорганизовать код. Это изменение мышления, необходимое для тестирования / насмешки / инъекции.

0
ответ дан 7 December 2019 в 07:46
поделиться