rspec 模块方法未定义方法的测试委托
rspec testing delegation for module method undefined method
此模块包含在 rails 中的表单对象中。
使用 rspec 测试它的正确方法是什么?
1) 我是否直接在包含它的每个模型上测试它?
或
2) 是否直接测试委托方法? (如果可能我更喜欢直接)
如果我直接测试,怎么样?我尝试并得到以下错误...
表单对象模块
module Registration
class Base
module ActAsDelegation
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def form_fields_mapping
[
{name: :first, model: :user},
{name: :address, model: :address}
]
end
def fields_of_model(model)
form_fields_mapping.select {|record| record[:model] == model }.map {|record| record[:name] }
end
def delegate_fields_to(*models)
models.each do |model|
fields_of_model(model).each do |attr|
delegate attr.to_sym, "#{attr}=".to_sym, to: model if attr.present?
end
end
end
end
end
end
end
表单对象
module Registration
class Base
include ActiveModel::Model
include ActAsDelegation
def initialize(user=nil, attributes={})
error_msg = "Can only initiate inherited Classes of Base, not Base Directly"
raise ArgumentError, error_msg if self.class == Registration::Base
@user = user
setup_custom_accessors
unless attributes.nil?
(self.class.model_fields & attributes.keys.map(&:to_sym)).each do |field|
public_send("#{field}=".to_sym, attributes[field])
end
end
validate!
end
end
end
RSPEC 测试
require "rails_helper"
RSpec.describe Registration::Base::ActAsDelegation, type: :model do
describe "Class Methods" do
context "#delegate_fields_to" do
let(:user) {spy('user')}
let(:address) {spy('address')}
let(:delegation_fields) { [
{name: :first, model: :user},
{name: :address, model: :address}
]}
it "should delegate" do
allow(subject).to receive(:form_fields_mapping) { delegation_fields }
Registration::Base::ActAsDelegation.delegate_fields_to(:user,:address)
expect(user).to have_received(:first)
expect(address).to have_received(:address)
end
end
end
end
错误
Failure/Error:
Registration::Base::ActAsDelegation.delegate_fields_to(:user,:address)
NoMethodError:
undefined method `delegate_fields_to' for Registration::Base::ActAsDelegation:Module
Did you mean? delegate_missing_to
(我在这个例子中还有其他代码问题,但下面解决了主要问题)
由于您的模块旨在包含,因此只需将其包含在测试中的空 class 中。我准备了一个简化的例子,我验证它可以工作:
module ToBeIncluded
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def a_class_method
:class
end
end
end
class TestSubject
include ToBeIncluded
end
require 'rspec/core'
RSpec.describe ToBeIncluded do
subject { TestSubject }
it 'returns correct symbol' do
expect(subject.a_class_method).to eq(:class)
end
end
在你的情况下,可能按照这些思路应该没问题:
require "rails_helper"
RSpec.describe Registration::Base::ActAsDelegation, type: :model do
class TestClass
include Registration::Base::ActAsDelegation
end
describe "Class Methods" do
context "#delegate_fields_to" do
let(:user) {spy('user')}
let(:address) {spy('address')}
let(:delegation_fields) { [
{name: :first, model: :user},
{name: :address, model: :address}
]}
it "should delegate" do
allow(TestClass).to receive(:form_fields_mapping) { delegation_fields }
TestClass.delegate_fields_to(:user,:address)
expect(user).to have_received(:first)
expect(address).to have_received(:address)
end
end
end
end
此外,如果您害怕名字冲突,您可以匿名class。
此模块包含在 rails 中的表单对象中。
使用 rspec 测试它的正确方法是什么?
1) 我是否直接在包含它的每个模型上测试它?
或
2) 是否直接测试委托方法? (如果可能我更喜欢直接)
如果我直接测试,怎么样?我尝试并得到以下错误...
表单对象模块
module Registration
class Base
module ActAsDelegation
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def form_fields_mapping
[
{name: :first, model: :user},
{name: :address, model: :address}
]
end
def fields_of_model(model)
form_fields_mapping.select {|record| record[:model] == model }.map {|record| record[:name] }
end
def delegate_fields_to(*models)
models.each do |model|
fields_of_model(model).each do |attr|
delegate attr.to_sym, "#{attr}=".to_sym, to: model if attr.present?
end
end
end
end
end
end
end
表单对象
module Registration
class Base
include ActiveModel::Model
include ActAsDelegation
def initialize(user=nil, attributes={})
error_msg = "Can only initiate inherited Classes of Base, not Base Directly"
raise ArgumentError, error_msg if self.class == Registration::Base
@user = user
setup_custom_accessors
unless attributes.nil?
(self.class.model_fields & attributes.keys.map(&:to_sym)).each do |field|
public_send("#{field}=".to_sym, attributes[field])
end
end
validate!
end
end
end
RSPEC 测试
require "rails_helper"
RSpec.describe Registration::Base::ActAsDelegation, type: :model do
describe "Class Methods" do
context "#delegate_fields_to" do
let(:user) {spy('user')}
let(:address) {spy('address')}
let(:delegation_fields) { [
{name: :first, model: :user},
{name: :address, model: :address}
]}
it "should delegate" do
allow(subject).to receive(:form_fields_mapping) { delegation_fields }
Registration::Base::ActAsDelegation.delegate_fields_to(:user,:address)
expect(user).to have_received(:first)
expect(address).to have_received(:address)
end
end
end
end
错误
Failure/Error: Registration::Base::ActAsDelegation.delegate_fields_to(:user,:address)
NoMethodError: undefined method `delegate_fields_to' for Registration::Base::ActAsDelegation:Module Did you mean? delegate_missing_to
(我在这个例子中还有其他代码问题,但下面解决了主要问题)
由于您的模块旨在包含,因此只需将其包含在测试中的空 class 中。我准备了一个简化的例子,我验证它可以工作:
module ToBeIncluded
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def a_class_method
:class
end
end
end
class TestSubject
include ToBeIncluded
end
require 'rspec/core'
RSpec.describe ToBeIncluded do
subject { TestSubject }
it 'returns correct symbol' do
expect(subject.a_class_method).to eq(:class)
end
end
在你的情况下,可能按照这些思路应该没问题:
require "rails_helper"
RSpec.describe Registration::Base::ActAsDelegation, type: :model do
class TestClass
include Registration::Base::ActAsDelegation
end
describe "Class Methods" do
context "#delegate_fields_to" do
let(:user) {spy('user')}
let(:address) {spy('address')}
let(:delegation_fields) { [
{name: :first, model: :user},
{name: :address, model: :address}
]}
it "should delegate" do
allow(TestClass).to receive(:form_fields_mapping) { delegation_fields }
TestClass.delegate_fields_to(:user,:address)
expect(user).to have_received(:first)
expect(address).to have_received(:address)
end
end
end
end
此外,如果您害怕名字冲突,您可以匿名class。