假设我们有一个与另一个对象具有垂直依赖关系的对象
class Ship
def initialize
...
end
def launch
ShipLauncher.new(self, platform: platform)
end
end
class ShipLauncher
def initialize(ship, platform:)
...
end
end
我们想测试一下:
it do
allow(ShipLauncher).to receive(:new)
ship = Ship.new
ship.launch
expect(ShipLauncher).to have_received(:new).with(ship, platform: 'x')
end
直到现在一切似乎都很好,但如果我们像这样更改ShipLauncher类
class ShipLauncher
def initialize(ship, platform_number:)
...
end
end
测试将在不应该通过时传递,因为ShipLauncher类需要另一个参数。我做错了什么?我必须通过集成测试来测试它吗?如果ShipLauncher类隐藏了很大的复杂性,会发生什么?我必须存根所有依赖项?
答案 0 :(得分:1)
有一个名为"partial doubles"的功能可用于检查此内容。
首先,您需要启用它:
RSpec.configure do |config|
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
end
然后按照以下方式编写您的规范:
describe Ship do
it "launches a ship" do
ship = Ship.new
expect(ShipLauncher).to receive(:new).with(ship, platform: 'x')
ship.launch
end
end
这将传递原始代码:
> rspec ship_spec.rb
.
Finished in 0.00429 seconds (files took 0.19664 seconds to load)
1 example, 0 failures
现在,进行更改:
class ShipLauncher
def initialize(ship, platform_number:)
...
end
end
你会收到这个错误:
rspec ship_spec.rb
F
Failures:
1) Ship should receive new
Failure/Error: expect(ShipLauncher).to receive(:new).with(ship, platform: 'x')
Missing required keyword arguments: platform_number
# ./ship_spec.rb:30:in `block (2 levels) in <top (required)>'
Finished in 0.00437 seconds (files took 0.2022 seconds to load)
1 example, 1 failure
请注意,规范是而不是实际调用initialize
上的ShipLauncher
方法,您可以验证:
class ShipLauncher
def initialize(ship, platform_number:)
raise Exception, "This code should not be run!"
end
end
运行规范,在两种情况下都会得到相同的结果。部分double只是检查参数和方法名称是否与被模拟的对象匹配。