How to #let a JSON file in RSpec on Rails
How to #let a JSON file in RSpec on Rails
EDIT:
The solution seems to start with describe KayNein::Twitter do
instead of RSpec.describe KayNein::Twitter do
.
describe KayNein::Twitter do
RSpec.describe KayNein::Twitter do
Why is this the case?
Rails 5.2.1
Ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
Original Question
I have a class that initializes with a JSON file:
module KayNein
class Twitter < Handler
def initialize(json_file)
@website_hash = JSON.parse(json_file)
end
And I'm trying to write an RSpec:
RSpec.describe KayNein::Twitter do
let (:json_file) File.read(PATH_TO_FILE)
context "Initialized" do
subject = KayNein::Twitter.new(json_file)
end
end
But RSpec gives me this error:
An error occurred while loading ./spec/app/kay_nein/sites/twitter_spec.rb.
Failure/Error: subject = KayNein::Twitter.new(json_file)
`json_file` is not available on an example group (e.g. a `describe` or `context` block). It is only available from within individual examples (e.g. `it` blocks) or from constructs that run
in the scope of an example (e.g. `before`, `let`, etc).
# ./spec/app/kay_nein/sites/twitter_spec.rb:8:in `block (2 levels) in <top (required)>'
# ./spec/app/kay_nein/sites/twitter_spec.rb:7:in `block in <top (required)>'
# ./spec/app/kay_nein/sites/twitter_spec.rb:5:in `<top (required)>'
What am I doing wrong?
Even this gives me an error, so it has nothing to do with the file:
RSpec.describe KayNein::Twitter do
let (:json_file) "Hello world"
context "Initialized" do
subject = KayNein::Twitter.new(json_file)
end
end
also, does File.read return a value? I couldn't find it the documentation.
– BKSpurgeon
Sep 11 '18 at 1:11
@BKSpurgeon yes it is defined, I'm just not disclosing the file path here for the sake of privacy
– clockworkpc
Sep 11 '18 at 1:21
@BKSpurgeon yes, File.read returns a value, it reads it as a JSON file.
– clockworkpc
Sep 11 '18 at 1:23
are you pasting in the full file? is your test wrapped in a
it "returns a file" do write your test here end
?– BKSpurgeon
Sep 11 '18 at 1:41
it "returns a file" do write your test here end
3 Answers
3
Can you try something like this ?
let(:file) File.read(File.join('spec', 'fixtures', 'public', filename))
describe "File" do
it "should be a file" do
expect(file).to be_a File
end
it "should initialize and read the contents"
initialize_file = KayNein::Twitter.new(file)
expect(response.body["key"]).to eq(..)
end
end
I think this inadvertantly helped me solve it. I removed "RSpec" from
Rspec.describe
and now I can #let.– clockworkpc
Sep 11 '18 at 2:51
Rspec.describe
We have two ways to DRY up tests (before and let) that share an intersecting purpose, to create variables that are common across tests. For common variable instantiation, the Ruby community prefers let, and while before is often used to perform actions common across tests.
when you use the context you can initialize the let inside the context block like this, will work
describe KayNein::Twitter do
context "Initialized" do
let (:json_file) File.read(PATH_TO_FILE)
subject = KayNein::Twitter.new(json_file)
end
end
otherwise if you don't want to use context, can try this way
describe KayNein::Twitter do
let (:json_file) File.read(PATH_TO_FILE)
it "Initialized" do
subject = KayNein::Twitter.new(json_file)
end
end
You can think of let
as defining accessors. And those accessors are available only inside example blocks it
or specify
.
let
it
specify
You are trying to use json_file
(defined in let) inside a context
. And this is exactly what the error message is trying to tell you:
json_file
context
json_file
is not available on an example group (e.g. a describe
or
context
block). It is only available from within individual examples
(e.g. it
blocks) or from constructs that run in the scope of an
example (e.g. before
, let
, etc).
json_file
describe
context
it
before
let
You can fix it like this:
RSpec.describe KayNein::Twitter do
let (:json_file) File.read(PATH_TO_FILE)
context "Initialized" do
specify do # it instead of specify also works
subject = KayNein::Twitter.new(json_file)
expect(subject).not_to be_nil # this is just an example, not needed to
# get rid of the issue
end
end
end
or even better - define subject outside of example block (for reusability etc) like this:
RSpec.describe KayNein::Twitter do
let (:json_file) File.read(PATH_TO_FILE)
subject KayNein::Twitter.new(json_file)
context "Initialized" do
specify do # it instead of specify also works
expect(subject).not_to be_nil # this is just an example, not needed to
# get rid of the issue
end
end
end
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
have you defined: ` File.read(PATH_TO_FILE)`?
– BKSpurgeon
Sep 11 '18 at 1:09