I am using jruby(9.1.12.0) with rspec-rails(3.7.0).
I have the following method
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
And have added the tests for the same as
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
My specs fail stating
expected <Java::RandomRequest:0x1d09fb8e>
got <Java::RandomRequest:0x38482732>
How do we mock so that we received the same instance?
Instances of the Java::RandomRequest
and Java::RandomResponse
that you create in spec do not match those that you create in create_address
.
Try stubbing the classes to return the values you need like:
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
Also, you can collapse allow
in before
with expect... have_received
after create_address
call to a spy called before the create_address
action, e.g.:
# 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
Another option would be to use kind_of
/instance_of
/duck_type
argument matchers instead of stubs if you don't intend to check how exactly request and response are initialized, e.g. something like:
# 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
Lastly, you don't have to initialize some_key
with real secure key, double would be enough if you don't process and just pass to some stubbed class in the end:
let(:some_key) { double }