在 rspec 示例中隐式使用主题不起作用
Implicit using subject in rspec example doesn't work
我要测试模型关注 get_uniq_id 方法。
app/models/concerns/id_generation.rb
module IdGeneration
extend ActiveSupport::Concern
module ClassMethods
def get_uniq_id
id = ''
loop {
id = generate_id
break unless Ticket.find_by_token(id)
}
id
end
def generate_id
id = []
"%s-%d-%s-%d-%s".split('-').each{|v| id << (v.eql?('%s') ? generate_characters : generate_digits)}
id.join('-')
end
def generate_digits(quantity = 3)
(0..9).to_a.shuffle[0, quantity].join
end
def generate_characters(quantity = 3)
('A'..'Z').to_a.shuffle[0, quantity].join
end
end
end
spec/concerns/id_generation_spec.rb
require 'spec_helper'
describe IdGeneration do
class Dummy
include IdGeneration::ClassMethods
end
subject { Dummy.new }
it { should get_uniq_id.match(/[A-Z]{2}-[0-9]{2}-[A-Z]{2}-[0-9]{2}-[A-Z]{2}/) }
end
它抛出错误:
Failure/Error: it { should get_uniq_id.match(/[A-Z]{2}-[0-9]{2}-[A-Z]{2}-[0-9]{2}-[A-Z]{2}/) }
NameError:
undefined local variable or method `get_uniq_id' for #<RSpec::ExampleGroups::IdGeneration:0x00000001808c38>
如果我明确指定主题 it { should subject.get_uniq_id.match(/[A-Z]{2}-[0-9]{2}-[A-Z]{2}-[0-9]{2}-[A-Z]{2}/)
}。有效。
我需要明确指定主题吗?
您调用方法的方式 - 是的。需要在对象上调用该方法。在这种情况下,get_uniq_id
将在当前 运行 测试的上下文中执行,这就是弹出错误的原因。
您可以使用的快捷方式如下:
it { should respond_to :get_uniq_id }
这将执行类似于 subject.respond_to?(:get_uniq_id)
的测试。然而,方法调用需要显式接收者。
您可以更新您的测试,以便在您的示例中使用它,如果您稍微修改它:
require 'spec_helper'
describe IdGeneration do
class Dummy
include IdGeneration::ClassMethods
end
subject { Dummy.new }
def get_uniq_id
subject.get_uniq_id
end
it { should get_uniq_id.match(/[A-Z]{2}-[0-9]{2}-[A-Z]{2}-[0-9]{2}-[A-Z]{2}/) }
end
或者,将输出绑定到 subject
:
require 'spec_helper'
describe IdGeneration do
class Dummy
include IdGeneration::ClassMethods
end
let(:dummy) { Dummy.new }
subject { dummy }
describe "#get_uniq_id" do
subject { dummy.get_uniq_id }
it { should match(/[A-Z]{2}-[0-9]{2}-[A-Z]{2}-[0-9]{2}-[A-Z]{2}/) }
end
end
我要测试模型关注 get_uniq_id 方法。
app/models/concerns/id_generation.rb
module IdGeneration
extend ActiveSupport::Concern
module ClassMethods
def get_uniq_id
id = ''
loop {
id = generate_id
break unless Ticket.find_by_token(id)
}
id
end
def generate_id
id = []
"%s-%d-%s-%d-%s".split('-').each{|v| id << (v.eql?('%s') ? generate_characters : generate_digits)}
id.join('-')
end
def generate_digits(quantity = 3)
(0..9).to_a.shuffle[0, quantity].join
end
def generate_characters(quantity = 3)
('A'..'Z').to_a.shuffle[0, quantity].join
end
end
end
spec/concerns/id_generation_spec.rb
require 'spec_helper'
describe IdGeneration do
class Dummy
include IdGeneration::ClassMethods
end
subject { Dummy.new }
it { should get_uniq_id.match(/[A-Z]{2}-[0-9]{2}-[A-Z]{2}-[0-9]{2}-[A-Z]{2}/) }
end
它抛出错误:
Failure/Error: it { should get_uniq_id.match(/[A-Z]{2}-[0-9]{2}-[A-Z]{2}-[0-9]{2}-[A-Z]{2}/) }
NameError:
undefined local variable or method `get_uniq_id' for #<RSpec::ExampleGroups::IdGeneration:0x00000001808c38>
如果我明确指定主题 it { should subject.get_uniq_id.match(/[A-Z]{2}-[0-9]{2}-[A-Z]{2}-[0-9]{2}-[A-Z]{2}/)
}。有效。
我需要明确指定主题吗?
您调用方法的方式 - 是的。需要在对象上调用该方法。在这种情况下,get_uniq_id
将在当前 运行 测试的上下文中执行,这就是弹出错误的原因。
您可以使用的快捷方式如下:
it { should respond_to :get_uniq_id }
这将执行类似于 subject.respond_to?(:get_uniq_id)
的测试。然而,方法调用需要显式接收者。
您可以更新您的测试,以便在您的示例中使用它,如果您稍微修改它:
require 'spec_helper'
describe IdGeneration do
class Dummy
include IdGeneration::ClassMethods
end
subject { Dummy.new }
def get_uniq_id
subject.get_uniq_id
end
it { should get_uniq_id.match(/[A-Z]{2}-[0-9]{2}-[A-Z]{2}-[0-9]{2}-[A-Z]{2}/) }
end
或者,将输出绑定到 subject
:
require 'spec_helper'
describe IdGeneration do
class Dummy
include IdGeneration::ClassMethods
end
let(:dummy) { Dummy.new }
subject { dummy }
describe "#get_uniq_id" do
subject { dummy.get_uniq_id }
it { should match(/[A-Z]{2}-[0-9]{2}-[A-Z]{2}-[0-9]{2}-[A-Z]{2}/) }
end
end