我的理解是单元测试应该单独测试类,关注细粒度行为并尽可能使用 double /模拟替换其他类的对象。 (如果我在这里错了,请纠正我。)
我正在编写一个带有名为 MatchList
的类的 gem。 MatchList::new
有两个参数,每个参数都是另一个名为 MatchPhrase
的类的实例。 MatchPhrase
包含一些 MatchList
严重依赖的行为(即, 如果您将 MatchPhrase
以外的任何内容提供给 MatchList::new
,你会得到一堆“未定义的方法”错误)。
我当前的(幼稚的?)测试设置使用 let
语句来分配变量以供我的示例使用:
let(:query) { MatchPhrase.new('Good Eats') }
let(:candidate) { MatchPhrase.new('Good Grief') }
let(:match_list) { MatchList.new(query, candidate) }
我该如何编写这个单元测试?我是否认为应该在不调用 MatchPhrase
类的情况下完成?这可能吗?
作为引用,下面是 MatchList
类的样子:
class MatchList < Array
attr_reader :query, :this_phrase, :that_phrase
def initialize(query, candidate)
super(query.length)
@query = query
@this_phrase = query.dup
@that_phrase = candidate
find_matches until none?(&:nil?)
end
private
def find_matches
query.each.with_index do |this_token, i|
next unless self[i].nil?
that_token = this_token.best_match_in(that_phrase)
next if that_token.match?(that_token) &&
this_token != that_token.best_match_in(this_phrase)
self[i] = this_token.match?(that_token) ? that_token : NilToken.new
this_phrase.delete_once(this_token)
that_phrase.delete_once(that_token)
end
end
end
最佳答案
My understanding is that unit testing should test classes in isolation, focusing on granular behavior and substituting objects of other classes using doubles/mocks wherever possible. (Please correct me if I'm wrong here.)
根据我的理解,这是不正确的。 使用 double /模拟有优点也有缺点。
优点是您可以使用数据库、电子邮件等慢速服务并使用快速执行的对象模拟它。
缺点是您模拟的对象不是“真实的”对象,可能会让您感到惊讶并且行为与真实对象不同。
这就是为什么在可行的情况下最好使用真实的对象。 仅当您想加快测试速度或导致更简单的测试时才使用模拟。即使这样,也可以使用真实对象进行一项测试来验证它是否一切正常。这称为集成测试。
考虑到您的情况:
let(:query) { MatchPhrase.new('Good Eats') }
let(:candidate) { MatchPhrase.new('Good Grief') }
let(:match_list) { MatchList.new(query, candidate) }
mock query 或 candidate 确实没有优势。
关于ruby - 如何对严重依赖于其他类的类进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42064022/