Reputation: 4716
I'm writing an RSpec test for some code that uses the Google API Client for Gmail.
When I query an email, I get back a Google::Apis::GmailV1::Message
object.
For testing, I created a fixture file called 'gmail_message_spec.json' that replicates the important methods of the object, but as JSON:
{"id": "17d38b2e48f6fake",
"payload":
{"headers":
[{"name": "MIME-Version", "value": "1.0"},
{"name": "Date", "value": "Fri, 19 Nov 2021 09:56:27 -0500"},
{"name": "Message-ID", "value": "<CAG4LXW=jEzKkfOLnE5jOSo7ertC=gAj-6GKE1qO=P8KB19fake@mail.gmail.com>"},
{"name": "Subject", "value": "Make a simple message for testing"},
{"name": "From", "value": "Test Person <[email protected]>"},
{"name": "To", "value": "Test Person <[email protected]>"},
{"name": "Content-Type", "value": "multipart/alternative; boundary=\"000000000000cc6f1d05d1257a61\""}],
"mime_type": "multipart/alternative",
"parts":
[{"mime_type": "text/plain", "body": {"data": "This is a very simple message.\r\n"}},
{"mime_type": "text/html", "body": {"data": "<div dir=\"ltr\">This is a very simple message.</div>\r\n"}}]},
"snippet": "This is a very simple message."}
So, in my spec, I can load in this fixture as a demo response:
response = JSON.parse(File.read("#{Rails.root}/spec/fixtures/files/gmail_message_spec.json"), symbolize_names: true)
However, my code expects the response to be an object and tries to perform method calls:
response.payload.headers
Since the testing object is JSON, I'd need to access it like a hash:
response[:payload][:headers]
It seems my options are:
Manually re-create the Google::Apis::GmailV1::Message
object
Write a bunch of stubs: allow(response).to receive(:payload).and return(response[:payload])
Get the JSON to respond to methods as an object does.
I'm aiming for option #3 first. The other two options seem a bit tedious, especially #2.
Is there a way to get a Hash
with deeply symbolized keys to allow for method calls that retrieve keys?
Instead of having to write this: response[:payload][:headers]
I want to write this: response.payload.headers
Upvotes: 0
Views: 270
Reputation: 4716
Of course I just rubber ducked myself.
I can use OpenStruct: JSON.parse(File.read(), object_class: OpenStruct)
response = JSON.parse(File.read("#{Rails.root}/spec/fixtures/files/gmail_message_spec.json"), object_class: OpenStruct)
Thanks to Someth Victory and their very good Medium article from 2018.
Upvotes: 1