Uzz*_*zar 2 ruby rspec ruby-on-rails
有些东西告诉我,我在测试中缺少一个关键的概念/想法,或者(天堂禁止)ruby如何初始化对象.
我有一个类方法接受两个参数并返回所述类的实例.所以它看起来像这样:
class Manager
def self.run(first_arg, second_arg)
new(first_arg, second_arg)
end
end
Run Code Online (Sandbox Code Playgroud)
这是我的RSpec测试:
RSpec.describe Manager, type: :api do
let(:first_arg) { FactoryGirl.build_stubbed(:first_arg) }
let(:second_arg) { AccountMailer.new }
describe '::run' do
it "accepts two arguments" do
expect(Manager).to receive(:run).with(first_arg, second_arg)
Manager.run(first_arg, second_arg)
end
it "instantiates the class with 2 arguments" do
expect(Manager).to receive(:new).with(first_arg, second_arg)
Manager.run(first_arg, second_arg)
end
end
end
Run Code Online (Sandbox Code Playgroud)
由于(我相信)该方法:initialize被new调用,我将代码更新为:
class Manager
# add attr_reader for read access
attr_reader :first_arg, :second_arg
def initialize(first_arg, second_arg)
@first_arg = first_arg
@second_arg = second_arg
end
def self.run(first_arg, second_arg)
new(first_arg, second_arg)
end
end
Run Code Online (Sandbox Code Playgroud)
我的测试失败并返回此错误:
1) Manager#run instantiates the class
Failure/Error: expect(Manager).to receive(:new).with(first_arg, second_arg)
Wrong number of arguments. Expected 0, got 2.
Run Code Online (Sandbox Code Playgroud)
我的主要问题是:
为什么看起来我传递给初始化的方法没有在rspec中被选中?我希望测试能够通过,因为Manager.new,initialize如果没有在类中定义,如果没有传递2个参数,则会失败.
谁能指出我在这里缺少什么?感谢您的反馈.谢谢.
I.我能用这样的代码重新创建你的问题
class Manager
def self.run(a, b)
new(a, b)
end
end
RSpec.configure do |config|
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
end
RSpec.describe Manager, type: :api do
let(:a) { 1 }
let(:b) { 2 }
describe '::run' do
it 'instantiates the class with 2 arguments' do
expect(Manager).to receive(:new).with(a, b)
Manager.run(a, b)
end
end
end
Run Code Online (Sandbox Code Playgroud)
结果如下:
1) Manager#run instantiates the class with 2 arguments
Failure/Error: expect(Manager).to receive(:new).with(a, b)
Wrong number of arguments. Expected 0, got 2.
Run Code Online (Sandbox Code Playgroud)
这是因为验证功能.启用此设置(应该是)时,RSpec将确保该对象实现了被存根/模拟的接口.在这种情况下,RSpec会在该行上抛出一个错误expect(Manager).to receive(:new).with(a, b),因为它实际上会查看Manager该类并检查initialize是否可以使用2个参数.
如果您将管理器更改为如下所示,则示例将通过:
class Manager
attr_reader :a, :b
def initialize(a, b)
@a = a
@b = b
end
def self.run(a, b)
new(a, b)
end
end
Run Code Online (Sandbox Code Playgroud)
II.但是你真的不需要使用模拟来实现这样的功能.如果您只是检查是否返回了正确类型的实例,那么最好只看真实的实例.
RSpec.describe Manager, type: :api do
let(:a) { 1 }
let(:b) { 2 }
describe '::run' do
subject { described_class.run(a, b) }
it 'instantiates the class with 2 arguments' do
expect(subject).to be_an_instance_of(Manager)
end
it 'sets a to the first argument' do
expect(subject.a).to eq(a)
end
it 'sets b to the second argument' do
expect(subject.b).to eq(b)
end
end
end
Run Code Online (Sandbox Code Playgroud)
III.在这个例子中:
expect(Manager).to receive(:run).with(first_arg, second_arg)
Manager.run(first_arg, second_arg)
Run Code Online (Sandbox Code Playgroud)
您设置了一个断言,然后立即调用代码来传递该断言.所以没有真正测试任何东西.
正确模拟/存根是相当先进的测试概念,很容易弄错,所以如果你可以不用它,只是不用它,它会使事情变得更容易.
如果您想了解更多有关测试/何时模拟的信息.我推荐Sandi Metz的演讲.https://www.youtube.com/watch?v=URSWYvyc42M
| 归档时间: |
|
| 查看次数: |
4424 次 |
| 最近记录: |