【发布时间】:2016-07-27 22:21:53
【问题描述】:
如果我的问题措辞不好,请纠正我。
假设以下代码:
class Filters
def self.good ducks
ducks.select(&:good?)
end
end
当然可以像这样测试方法:
describe Filters, '#good' do
let(:good) { double(:good, good?: true) }
let(:bad) { double(:bad, good?: false) }
subject { Filters.good(ducks) }
context 'none' do
let(:ducks) { [] }
it { is_expected.to eq [] }
end
context 'one good' do
let(:ducks) { [good] }
it { is_expected.to eq [good] }
end
context 'one bad' do
let(:ducks) { [bad] }
it { is_expected.to eq [] }
end
context 'one good and one bad' do
let(:ducks) { [good, bad] }
it { is_expected.to eq [good] }
end
context 'some good and some bad' do
let(:ducks) { [good, bad, bad, good, bad, good] }
it { is_expected.to eq [good, good, good] }
end
end
但是列举所有的情况(当然不是所有的,但没有/一个/一些/很多对于真/假good状态的组合)让我觉得我实际上不是单位 测试该方法,但集成 测试它,因为我将select“泄漏”的行为知识“泄漏”到我的good 方法中,导致测试用例的数量成倍增加。从某种意义上说,我的测试用例正在测试select 方法的行为。
对我来说,使用模拟和检查(如检查而不是测试)方法是否正确委托似乎更合适。如果一个人与自己编写的函数集成,就可以做到这一点。类似于我们的方式,例如可以说expect(obj).to receive(:foo).with(:bar)。
下面的示例不起作用,但我相信它传达了我想要做的想法,而不是枚举所有案例。
describe Filters, '#good' do
it 'returns only good ones' do
ducks = double(:ducks)
expect(ducks).to receive(:filter).with(:good?).and_return(:filtered)
expect(Filters.good(ducks).to eq )
end
end
这个例子可能看起来微不足道,所以为了避免争论说这是一种无用的方法,Filter.good 的用户应该直接使用select,请考虑移动select-语句只会移动的事实需要到另一个地点进行测试。
我是否误解或忽略了一些基本的东西?
Ps 1. 为简洁起见,我忽略了一些测试用例。
Ps 2. 我强调需要 unit 而不是 integration 测试的原因的简短版本是这个视频:https://www.youtube.com/watch?v=VDfX44fZoMc
编辑:
表达这个问题的更好方法可能是:第一个测试是 classicist 如何测试Filters.good 的要点示例,但 mockist 将如何测试是吗?
【问题讨论】:
-
您找到解决方案了吗?
-
@PaulFioravanti 感谢您提供的答案。但在我看来,目前还没有解决方案。我正在对问题进行澄清。
标签: ruby unit-testing rspec mocking