Mockito проверяет чистый код [дубликат]

Если вы знаете, что существует только одна запись для группы, которая не является нулевой (или вам все равно, какой из них вы получите), вы можете использовать first:

import org.apache.spark.sql.functions.{first, last}

val df = Seq(
  ("a", Some(1), None, None), ("a", None, Some(2), None),
  ("a", None, None, Some(3))
).toDF("key", "value1", "value2", "value3")

df.groupBy("key").agg(
  first("value1", true) as "value1", 
  first("value2", true) as "value2", 
  first("value3", true) as "value3"
).show  

// +---+------+------+------+
// |key|value1|value2|value3|
// +---+------+------+------+
// |  a|     1|     2|     3|
// +---+------+------+------+

или last:

df.groupBy("key").agg(
  last("value1", true) as "value1", 
  last("value2", true) as "value2", 
  last("value3", true) as "value3"
).show  


// +---+------+------+------+
// |key|value1|value2|value3|
// +---+------+------+------+
// |  a|     1|     2|     3|
// +---+------+------+------+    
162
задан Ram 22 March 2016 в 18:53
поделиться

5 ответов

Это отличный вопрос! Я думаю, что основная причина этого заключается в следующем: мы используем JUnit не только для модульного тестирования. Поэтому вопрос должен быть разбит:

  • Должен ли я использовать Mockito.verify () в моем тестировании integration (или любом другом тестировании с более высоким уровнем)?
  • Должен ли я использовать Mockito.verify () в моем модульном тестировании с помощью черного ящика?
  • Должен ли я использовать Mockito.verify () в моем тестировании с ящиком?

, поэтому, если мы проигнорируем тестирование более высокого уровня, вопрос может быть перефразирован ». Использование блочного тестирования с помощью Mockito.verify () создает большую пару между модульным тестом и моим может ли я выполнить некоторые «серо-бокс» модульного тестирования и какие правила большого пальца я должен использовать для этого ».

Теперь давайте рассмотрим все эти пошаговые инструкции, step.

* - Должен ли я использовать Mockito.verify () в моем тестировании (или любое другое тестирование, отличное от единицы измерения)? * Я думаю, что ответ явно отсутствует , кроме того, вы не должны использовать для этого макеты. Ваш тест должен быть как можно ближе к реальному приложению. Вы тестируете полный прецедент, а не отдельную часть приложения.

* black-box vs white-box unit-testing * Если вы используете подход «черный ящик», что вы действительно делаете, вы предоставляете (все классы эквивалентности) вход, state и проверяет, что вы получите ожидаемый результат. В этом подходе использование оправданий в целом оправдано (вы просто имитируете, что они поступают правильно, вы не хотите их тестировать), но вызов Mockito.verify () является излишним.

Если вы используете метод white-box, что вы действительно делаете, вы тестируете поведение вашего устройства. В этом подходе необходимо обратиться к Mockito.verify (), вы должны убедиться, что ваш аппарат ведет себя так, как вы ожидаете.

правила больших пальцев для серого теста. Проблема с тестированием белого ящика это создает высокое сцепление. Одним из возможных решений является серо-бокс-тестирование, а не white-box-testing. Это своего рода сочетание черного и белого ящиков. Вы действительно тестируете поведение вашего устройства, как в белом режиме, но, как правило, вы делаете его агностиком , когда это возможно . Когда это возможно, вы просто сделаете чек, как в случае с черным ящиком, просто утверждают, что результат - это то, что вы ожидаете. Итак, суть вашего вопроса - когда это возможно.

Это действительно сложно. У меня нет хорошего примера, но я могу привести примеры. В случае, упомянутом выше с equals () vs equalsIgnoreCase (), вы не должны называть Mockito.verify (), просто подтверждайте вывод. Если вы не смогли этого сделать, сложите свой код на меньшую единицу, пока вы не сможете это сделать. С другой стороны, предположим, что у вас есть @Service, и вы пишете @ Web-сервис, который по существу является оберткой на вашем @Service - он делегирует все вызовы @Service (и делает дополнительную обработку ошибок). В этом случае необходимо вызвать Mockito.verify (), вы не должны дублировать все ваши проверки, которые вы сделали для @Serive, достаточно проверить, что вы вызываете @Service с правильным списком параметров.

22
ответ дан alexsmail 3 September 2018 в 18:21
поделиться

Как говорили некоторые люди

  1. Иногда у вас нет прямого вывода, на котором вы можете утверждать
  2. Иногда вам просто нужно подтвердить, что ваш протестированный метод отправляет правильные косвенные результаты для своих соавторов (которые вы издеваетесь).

Что касается вашей озабоченности по поводу нарушения ваших тестов при рефакторинге, то это несколько ожидается при использовании mocks / stubs / spies. Я имею в виду, что по определению, а не в отношении конкретной реализации, такой как Mockito. Но вы могли бы подумать таким образом - если вам нужно сделать рефакторинг, который создаст серьезные изменения в способе работы вашего метода, рекомендуется сделать это на основе TDD-подхода, то есть вы можете сначала изменить свой тест, чтобы определить новое поведение (которое не пройдет тест), а затем сделайте изменения и снова проверите тест.

0
ответ дан Emanuel Luiz Lariguet Beltrame 3 September 2018 в 18:21
поделиться

Я должен сказать, что вы абсолютно правы с точки зрения классического подхода:

  • Если вы впервые создали (или изменили) бизнес-логику вашего приложения и затем покрывают его с помощью (принятия) тестов ( Test-Last approach ), тогда будет очень болезненно и опасно позволить тестам знать что-либо о том, как работает ваше программное обеспечение, другое чем проверка входов и выходов.
  • Если вы практикуете подход Test-Driven , то ваши тесты - это , которые должны быть записаны, чтобы быть изменены, и чтобы отразить использование функций вашего программного обеспечения. Реализация зависит от тестов. Иногда это означает, что вы хотите, чтобы ваше программное обеспечение было реализовано определенным образом, например. полагаться на какой-то другой компонент или даже называть его определенное количество раз. Вот где Mockito.verify () пригодится!

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

6
ответ дан hammelion 3 September 2018 в 18:21
поделиться

Ответ Дэвида, конечно, правильный, но не совсем объясняет, зачем вам это нужно.

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

Например, у вас есть бит бизнес-логики, который должен хранить вещи с помощью DAO. Вы можете сделать это с помощью теста интеграции, который создает экземпляр DAO, подключает его к бизнес-логике и затем запихивает в базу данных, чтобы узнать, сохранен ли ожидаемый материал. Это уже не единичный тест.

Или вы можете издеваться над DAO и убедиться, что он вызван так, как вы ожидаете. С помощью mockito вы можете проверить, что что-то вызывается, как часто оно называется, и даже использовать сопоставления по параметрам, чтобы гарантировать, что он будет вызван определенным образом.

Откидная сторона модульного тестирования, как это, действительно что вы связываете тесты с реализацией, что делает рефакторинг немного сложнее. С другой стороны, хороший дизайн-запах - это количество кода, которое требуется для правильного его использования. Если ваши тесты должны быть очень длинными, возможно, что-то не так с дизайном. Поэтому код с большим количеством побочных эффектов / сложных взаимодействий, которые необходимо протестировать, вероятно, не очень хорошо.

47
ответ дан Jilles van Gurp 3 September 2018 в 18:21
поделиться

Если договор класса A включает в себя тот факт, что он вызывает метод B объекта типа C, тогда вы должны проверить это, сделав макет типа C и проверив, что метод B. был вызван.

Это означает, что контракт класса A имеет достаточно подробные сведения о том, что он говорит о типе C (который может быть интерфейсом или классом). Итак, да, мы говорим о уровне спецификации, который выходит за рамки только «системных требований» и имеет некоторый способ описания реализации.

Это нормально для модульных тестов. Когда вы проводите модульное тестирование, вы хотите, чтобы каждый блок выполнял «правильную вещь» и обычно включал его взаимодействие с другими подразделениями. «Единицы» здесь могут означать классы или более крупные подмножества вашего приложения.

Обновление:

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

По моему опыту, если я изменить реализацию класса, мне часто приходится менять реализацию своих модульных тестов для соответствия. Однако, как правило, мне не придется менять инвентаризацию того, какие модульные тесты существуют для класса; если, разумеется, причиной изменения было наличие условия, которое я ранее не тестировал.

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

63
ответ дан tkruse 3 September 2018 в 18:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: