Модульное тестирование вспомогательных или неинтерфейсных признаков в Scala

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

у меня простой Crawler класс, который зависит от HttpConnection и HttpHelpers набор служебных функций. Давайте теперь сосредоточимся на HttpHelpers.

In Java, HttpHelpers, возможно, будет служебным классом и передаст свой синглтон искателю в качестве зависимости либо вручную, либо с помощью некоторой структуры IoC. Тестирование Crawler является простым, так как зависимость легко издеваться.

В Scala кажется помощник черта является более предпочтительным способом составления функциональности. Действительно, его проще использовать (методы, автоматически импортируемые в пространство имен при расширении, могут использовать withResponse ... вместо из httpHelper.withResponse ..., etc.). Но как это влияет на тестирование?

это мое решение, которое я придумал, но, к сожалению, оно поднимает некоторую шаблонную панель на сторону тестирования.

помощник черта:

trait HttpHelpers {
  val httpClient: HttpClient
  protected def withResponse[A](resp: HttpResponse)(fun: HttpResponse => A): A = // ...
  protected def makeGetRequest(url: String): HttpResponse = // ...
}

код для проверки:

class Crawler(val httpClient: HttpClient) extends HttpHelpers {
  // ...
}

2 ответов


вы можете написать вспомогательный макет, который должен быть смешан с HttpHelpers и переопределить его методы с помощью макетного эквивалента:

trait HttpHelpersMock { this: HttpHelpers =>

  //MOCK IMPLEMENTATION
  override protected def withResponse[A](resp: HttpResponse)(fun: HttpResponse => A): A = // ...

  //MOCK IMPLEMENTATION
  override protected def makeGetRequest(url: String): HttpResponse = // ...
}

затем, при тестировании crawler, вы смешиваете макет признака при создании экземпляра:

val crawlerTestee = new Crawler(x) with HttpHelpersMock

и макетные методы просто заменят вспомогательные методы в instance crawlerTestee.

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

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


Как насчет:

val helpers = new HttpHelpers {
  //override or define stuff the trait needs to work properly here
}

helpers.someMethodToTest

Смотри, Ма, без промежуточных черты и насмешливый библиотеки нужны!

Я делаю это все время для моих черт, и я был очень доволен результатом.