Этот вопрос касается тестирования классов, которые смешиваются в неинтерфейсных чертах, то есть чертах, содержащих некоторую функциональность. При тестировании функциональность класса должна быть изолирована от функциональности, обеспечиваемой чертой добавления (которая предположительно тестируется отдельно).
У меня есть простой Crawler
класс, который зависит от HttpConnection и HttpHelpers
набора служебных функций. Давайте сосредоточимся на HttpHelpers сейчас.
В Java HttpHelpers, возможно, будет служебным классом и передаст свой синглтон Crawler в качестве зависимости, либо вручную, либо с некоторой платформой IoC. Тестировать Crawler просто, так как зависимость легко подделать.
В Scala кажется, что вспомогательная черта является более предпочтительным способом создания функциональности. Действительно, его проще использовать (методы, автоматически импортируемые в пространство имен при расширении, могут использовать withResponse ...
вместо httpHelper.withResponse ...
и т. Д.). Но как это влияет на тестирование?
Это мое решение, которое я придумала, но, к сожалению, оно поднимает некоторый шаблон на сторону тестирования.
Хелперная черта:
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 {
// ...
}
Тест:
// Mock support trait
// 1) Opens up protected trait methods to public (to be able to mock their invocation)
// 2) Forwards methods to the mock object (abstract yet)
trait MockHttpHelpers extends HttpHelpers {
val myMock: MockHttpHelpers
override def makeGetRequest(url: String): HttpResponse = myMock.makeGetRequest(url)
}
// Create our mock using the support trait
val helpersMock = Mockito.mock(classOf[MockHttpHelpers])
// Now we can do some mocking
val mockRequest = // ...
Mockito when (helpersMock.makeGetRequest(Matchers.anyString())) thenReturn mockRequest
// Override Crawler with the mocked helper functionality
class TestCrawler extends Crawler(httpClient) with MockHttpHelpers {
val myMock = helpersMock
}
// Now we can test
val crawler = new TestCrawler()
crawler.someMethodToTest()
Вопрос
Этот подход работает, но необходимость иметь фиктивную черту поддержки для каждой черты помощника немного утомительна. Однако я не вижу другого способа, чтобы это сработало.
- Это правильный подход?
- Если это так, может ли его цель быть достигнута более эффективно (магия синтаксиса, плагин компилятора и т. Д.)?
Любые отзывы приветствуются. Спасибо!