动态生成的模拟对象 + rspec-mock
Mocking object that are generated dynamically + rspec-mock
我正在使用 jruby(9.1.12.0) 和 rspec-rails(3.7.0).
我有以下方法
class AddressCreator
include Singleton
attr_reader :client
def initialize
@client = SomeJavaClass.new(some keys go here)
end
end
# SomeJavaClass has an create_address instance method.
def create_address(user_id, address)
req = Java::RandomRequest.new(user_id, address)
resp = Java::RandomResponse.new(default_response_params)
AddressCreator.instance.client.create_address(some_key, req, resp)
end
并添加了与
相同的测试
describe '#create_address' do
let(:some_key) { SecureRandom.uuid }
let(:user_id) { 1 }
let(:default_response_params) { false }
let(:address) { 'some address goes here' }
let(:request) { Java::RandomRequest.new(address)}
let(:response) { Java::RandomResponse.new(default_response_params)}
before {allow(AddressCreator.instance.client).to receive(:create_address).with(some_key, request, response).and_return(response)}
it 'should create the address' do
result = AddressCreator.instance.client.create_address some_key
expect(AddressCreator.singleton).to have_received(:create_address).with(some_key, request, response) do |request|
expect(request.is_success).to eq(response.is_success)
end
expect(result).to eq(response)
end
end
我的规格没有说明
expected <Java::RandomRequest:0x1d09fb8e>
got <Java::RandomRequest:0x38482732>
我们如何模拟才能接收到相同的实例?
您在规范中创建的 Java::RandomRequest
和 Java::RandomResponse
实例与您在 create_address
中创建的实例不匹配。
尝试将 classes 存入 return 您需要的值,例如:
let(:request) { instance_double(Java::RandomRequest) }
let(:response) { instance_double(Java::RandomResponse) }
before do
allow(Java::RandomRequest).to receive(:new).and_return(request)
allow(Java::RandomResponse).to receive(:new).and_return(response)
end
此外,您可以在 before
中用 expect... have_received
在 create_address
调用一个在 create_address
操作之前调用的间谍之后折叠 allow
,例如:
# no before block
it 'should create the address' do
expect(AddressCreator.singleton)
.to receive(:create_address)
.with(some_key, request, response) do |request|
expect(request.is_success).to eq(response.is_success)
end
result = AddressCreator.instance.client.create_address some_key
expect(result).to eq(response)
end
另一种选择是使用 kind_of
/instance_of
/duck_type
参数匹配器而不是存根,如果您不打算检查请求和响应的初始化方式,例如类似于:
# no before
it 'should create the address' do
expect(AddressCreator.singleton).to receive(:create_address)
.with(kind_of(String), instance_of(Java::RandomRequest), duck_type(:is_success)) do |request|
expect(request.is_success).to be_true
end
AddressCreator.instance.client.create_address some_key
end
最后,您不必使用真正的安全密钥初始化 some_key
,如果您不处理并在最后传递给一些存根的 class,那么双倍就足够了:
let(:some_key) { double }
我正在使用 jruby(9.1.12.0) 和 rspec-rails(3.7.0).
我有以下方法
class AddressCreator
include Singleton
attr_reader :client
def initialize
@client = SomeJavaClass.new(some keys go here)
end
end
# SomeJavaClass has an create_address instance method.
def create_address(user_id, address)
req = Java::RandomRequest.new(user_id, address)
resp = Java::RandomResponse.new(default_response_params)
AddressCreator.instance.client.create_address(some_key, req, resp)
end
并添加了与
相同的测试describe '#create_address' do
let(:some_key) { SecureRandom.uuid }
let(:user_id) { 1 }
let(:default_response_params) { false }
let(:address) { 'some address goes here' }
let(:request) { Java::RandomRequest.new(address)}
let(:response) { Java::RandomResponse.new(default_response_params)}
before {allow(AddressCreator.instance.client).to receive(:create_address).with(some_key, request, response).and_return(response)}
it 'should create the address' do
result = AddressCreator.instance.client.create_address some_key
expect(AddressCreator.singleton).to have_received(:create_address).with(some_key, request, response) do |request|
expect(request.is_success).to eq(response.is_success)
end
expect(result).to eq(response)
end
end
我的规格没有说明
expected <Java::RandomRequest:0x1d09fb8e>
got <Java::RandomRequest:0x38482732>
我们如何模拟才能接收到相同的实例?
您在规范中创建的 Java::RandomRequest
和 Java::RandomResponse
实例与您在 create_address
中创建的实例不匹配。
尝试将 classes 存入 return 您需要的值,例如:
let(:request) { instance_double(Java::RandomRequest) }
let(:response) { instance_double(Java::RandomResponse) }
before do
allow(Java::RandomRequest).to receive(:new).and_return(request)
allow(Java::RandomResponse).to receive(:new).and_return(response)
end
此外,您可以在 before
中用 expect... have_received
在 create_address
调用一个在 create_address
操作之前调用的间谍之后折叠 allow
,例如:
# no before block
it 'should create the address' do
expect(AddressCreator.singleton)
.to receive(:create_address)
.with(some_key, request, response) do |request|
expect(request.is_success).to eq(response.is_success)
end
result = AddressCreator.instance.client.create_address some_key
expect(result).to eq(response)
end
另一种选择是使用 kind_of
/instance_of
/duck_type
参数匹配器而不是存根,如果您不打算检查请求和响应的初始化方式,例如类似于:
# no before
it 'should create the address' do
expect(AddressCreator.singleton).to receive(:create_address)
.with(kind_of(String), instance_of(Java::RandomRequest), duck_type(:is_success)) do |request|
expect(request.is_success).to be_true
end
AddressCreator.instance.client.create_address some_key
end
最后,您不必使用真正的安全密钥初始化 some_key
,如果您不处理并在最后传递给一些存根的 class,那么双倍就足够了:
let(:some_key) { double }