我有一个名为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
}
}
测试时,请使用mockito
和spec2
:
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
方法现在非常简单,不需要直接的单元测试。