ron*_*ron 14 unit-testing scala traits
这个问题是关于处理混合非接口特征的类的测试,这是包含一些功能的特征.在测试时,类功能应该与混合特性(假设单独测试)提供的功能隔离.
我有一个简单的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 = // ...
}
Run Code Online (Sandbox Code Playgroud)
要测试的代码:
class Crawler(val httpClient: HttpClient) extends HttpHelpers {
// ...
}
Run Code Online (Sandbox Code Playgroud)
测试:
// 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()
Run Code Online (Sandbox Code Playgroud)
题
这种方法可以完成这项工作,但需要为每个帮助程序特征设置一个模拟支持特性,这有点单调乏味.但是,我看不到任何其他方式可以工作.
欢迎任何反馈.谢谢!
您可以编写一个Helper模拟特征,它应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 = // ...
}
Run Code Online (Sandbox Code Playgroud)
然后,在测试爬虫时,在实例化时混合模拟特征:
val crawlerTestee = new Crawler(x) with HttpHelpersMock
Run Code Online (Sandbox Code Playgroud)
而mock方法只会替换实例中的helper方法crawlerTestee.
编辑:我不认为测试类如何与辅助特征交互是一个好主意.在我看来,您应该测试Crawler行为而不是其内部实现细节.实现可以改变,但行为应尽可能保持稳定.我上面描述的过程允许您覆盖辅助方法,使其确定性并避免真正的网络,从而帮助和加快测试.
但是,我认为测试Helper本身是有意义的,因为它可以在其他地方重复使用并具有适当的行为.
| 归档时间: |
|
| 查看次数: |
5233 次 |
| 最近记录: |