gpt4 book ai didi

unit-testing - Scala 中的单元测试助手或非接口(interface)特征

转载 作者:行者123 更新时间:2023-12-03 22:36:20 24 4
gpt4 key购买 nike

这个问题是关于处理混合非接口(interface)特征的类的测试,即包含一些功能的特征。测试时,类功能应该与 mix-in trait 提供的功能隔离(应该是单独测试的)。

我有一个简单的Crawler类,它依赖于一个 HttpConnection 和一个 HttpHelpers效用函数的集合。现在让我们关注 HttpHelpers。

在 Java , HttpHelpers 可能是一个实用程序类,并将其单例作为依赖项传递给 Crawler,无论是手动还是使用某些 IoC 框架。测试爬虫很简单,因为依赖很容易模拟。

在 Scala 似乎辅助特征是组合功能的更优选方式。确实,它更容易使用(扩展时自动导入命名空间的方法,可以使用 withResponse ... 代替 httpHelper.withResponse ... 等)。但它如何影响测试?

这是我想出的解决方案,但不幸的是,它将一些样板文件提升到了测试端。

helper 特质:

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()

问题

这种方法确实有效,但是需要为每个辅助 trait 提供一个模拟支持 trait 有点乏味。但是,我看不到任何其他方法可以使它起作用。
  • 这是正确的方法吗?
  • 如果是,是否可以更有效地实现其目标(语法魔术、编译器插件等)?

  • 欢迎任何反馈。谢谢!

    最佳答案

    你可以编写一个 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 = // ...
    }

    然后,在测试爬虫时,在实例化时混合模拟特征:
    val crawlerTestee = new Crawler(x) with HttpHelpersMock

    而模拟方法只会替换实例 crawlerTestee 中的辅助方法。 .

    编辑:我认为测试一个类如何与辅助特征交互不是一个好主意。在我看来,你应该测试 Crawler行为而不是其内部实现细节。实现可以改变,但行为应尽可能保持稳定。我上面描述的过程允许您覆盖辅助方法以使它们具有确定性并避免真正的网络,从而帮助和加速测试。

    但是,我认为测试 Helper 本身是有意义的,因为它可以在其他地方重用并且具有正确的行为。

    关于unit-testing - Scala 中的单元测试助手或非接口(interface)特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7059859/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com