当你想在测试中模拟一个繁重的方法时,如何在scala中设计类



我有一个名为HtmlConverter的类,它可以将html页面转换为纯文本文件,并且可以从URL中检索html内容。

我想对它进行单元测试,所以我想模拟"从 url 检索 html"部分。现在我有两个选择:

1. 定义一个对象HtmlRetriever并在HtmlConverter中使用它

法典:

class HtmlRetriever {
    def getContentFromUrl(url:String) = { 
        // heavy work
    }
}
class HtmlConverter {
    val retriever = new HtmlRetriever
    def convertFromUrl(url:String) = {
         val content = retriever.getContentFromUrl(url)
         // convert
    }
}

测试时,请使用mockitospec2

object MyHtmlConverter extends HtmlConverter {
    override val retriever = mock[HtmlRetriever]
}
MyHtmlConverter.retriever.getContentFromUrl(...) returns "<html>...</html>"
val pdf = MyHtmlConterter.convertFromUrl(...)
// assert the invocation
there was one(MyHtmlConverter.retriever).getContentFromUrl(...)

有效,但我不确定这是否是最佳解决方案

2. 使用特质

现在我想尝试一个特质

trait HtmlRetriever {
    def getContentFromUrl(url:String) = { 
        // heavy work
    }
}
class HtmlConverter extends HtmlRetriever {
    def convertFromUrl(url:String) = {
         val content = getContentFromUrl(url)
         // convert
    }
}

测试时找不到使用mockito的方法,只能使用我的自定义覆盖方法:

object MyHtmlConverter extends HtmlConverter {
    override def getContentFromUrl(url:String) = "<html>from test</html"
}

然后使用新的getContentFromUrl方法测试对象MyHtmlConverter

这样,我就无法使用mockito,因此我无法验证调用,例如:

there was one(htmlRetriever).getContentFromUrl(...)

我都不满意

有没有最佳实践在scala中进行这种测试,使用mockito或其他东西。

您可以创建一个类的声明,以扩展测试中的特征,然后模拟该类:

class TestHtmlConverter extends HtmlConverter
/* other code elided */
val htmlConverter = mock[TestHtmlConverter]
htmlConverter.getContentFromUrl(/* ... */) returns "<html />"

您可以以不同的方式构建方法,以避免完全需要模拟。

class HtmlConverter {
    val retriever = new HtmlRetriever
    def convertFromUrl(url:String) = {
         val content = retriever.getContentFromUrl(url)
         convert(content)
    }
    def convert(content: ContentFromUrl) = {
        // convert
    }
}

然后,您可以直接测试convert。一套不同的测试可以涵盖retriever,并且您的convertFromUrl方法现在非常简单,不需要直接的单元测试。

相关内容

  • 没有找到相关文章

最新更新