I'm trying to mock a zendesk API response that's called like this:
zendesk_client = ZendeskHelper.make_client
tickets = zendesk_client.search.export(query)
The application iterates through all the pages in a Zendesk API request using the API's .all!
method:
tickets.all! do |ticket|
# do something
end
Initially, I put some doubles in an array and used that as a mock response:
mock_tickets = [
double('ticket'),
double('ticket'),
double('ticket')
]
allow(mock_zendesk_client).to receive_message_chain(:search, :export).and_return(mock_tickets)
But I get a syntax error because a normal array cannot use the .all!
method.
I inspected the real tickets
response, and it was a ZendeskAPI::Collection
object. How can I mock this object so my mock response can use the .all!
method?
The .all!
method looks like this
def all!(start_page = @options["page"], &block)
_all(start_page, :bang, &block)
end
...
def _all(start_page = @options["page"], bang = false, &block)
raise(ArgumentError, "must pass a block") unless block
page(start_page)
clear_cache
while (bang ? fetch! : fetch)
each do |resource|
arguments = [resource, @options["page"] || 1]
if block.arity >= 0
arguments = arguments.take(block.arity)
end
block.call(*arguments)
end
last_page? ? break : self.next
end
page(nil)
clear_cache
end
CodePudding user response:
Usually when you get into a situation like you're in trying to deep-mock some third party's API response, you'll find that you're actually testing the third party's API, not your own code.
You should have a layer above the Zendesk response that's full of objects YOUR code is creating, mock THERE instead.
CodePudding user response:
Got a suggestion from a senior dev, the solution is to mock the implementation of .all!
.
mock_items = [double('mock_item')]
mock_response = double('mock_response',
# need to have `all!` here, else you'll get error saying the double doesn't implement `.all!`
all!: ''
)
allow(mock_response).to receive(:all) do |&block|
# iterates through the items using the block that follows .all!
mock_items.each do |item|
block.call(item)
end
end