graphql-ruby
graphql-ruby copied to clipboard
Using dataloader on a mutation with rspec-mocks + lazy-evaluated mocked method causes code to hang
Once again, thanks for this amazing gem. I'm pretty excited about experimenting with the dataloader for the first time. I've used lazy execution in the past to deal with n+1s in a Rails app, and the dataloader API feels pretty neat!
Describe the bug
Consider a doSomething
mutation, plugged into a schema with the dataloader enabled, and a resolver such as this one:
def resolve
DoerOfSomething.do_something
{ done: true }
end
And the following rspec test scenario:
subject(:mutation) do
TestSchema.execute(query, variables: {}, context: {})
end
let(:query) do
<<~GQL
mutation DoSomething {
doSomething(input: {}) {
done
}
}
GQL
end
before do
allow(DoerOfSomething).to receive(:do_something) do
puts 'Evaluating mocked_return_value using block_syntax'
result = mocked_return_value # <- the test hangs when the resolver calls DoerOfSomething.do_something and we reach this line
puts 'Finished evaluating the let statement for the mocked return value'
result
end
# If I use `.and_return(mocked_return_value)` it does not hang.
# If I use `let!` (eager version) when defining `mocked_return_value`, it does not hang
# If I force rspec to evaluate `mocked_return_value` before the mutation runs, it does not hang (which is what happened when using `.and_return`
end
it 'should run and complete' do
subject
expect(true).to be_truthy
puts "Test finished"
end
The statements 'Finished evaluating the let statement for the mocked return value' and "Test finished" never get printed, and the test hangs forever.
The test is hanging when the lazy let
statement is evaluated.
Versions
graphql
version: 2.0.13 (but the bug was first identified on 1.12.5)
rails
(or other framework): 7.0.3.1
other applicable versions (graphql-batch
, etc)
rspec-rails (5.1.2)
rspec-core (3.11.0)
rspec-expectations (3.11.0)
rspec-mocks (3.11.1)
GraphQL schema
Please see this PR offering a minimal example.
Steps to reproduce
The easiest way is to use the repo I've created and run the tests:
git clone [email protected]:khamusa/gql-dataloader-rspec-mocks-hanging.git
cd gql-dataloader-rspec-mocks-hanging
git checkout bug-demo
bundle
bundle exec rspec
The failing test is on the bug-demo
branch. You can see the diff on this PR if you'd rather not clone and run the repo directly (you'll need graphql and rspec-rails gems - or rspec directly, as I don't see how rails itself could be related). I've left some comments there stating what I have found so far (not much, sorry :( )
I came across this issue when working with mutations, but, in principle, it should affect queries as well.
Expected behavior
The lazily-defined let
statement can be resolved successfully when dataloader is enabled, just like it is when dataloader is not plugged into the schema.
Actual behavior
The code hangs when trying to evaluate the mocked method that would return a lazy-evaluated let statement.
Thanks for this great report and reproduction of the issue. I'll take a look soon and see if I can get to the bottom of it!
I cloned your replication repo and inspected the stuck process, I think it might be an issue in Rspec, so I opened https://github.com/rspec/rspec-support/issues/552. I'll keep an eye on that in the meantime.
Sorry, I don't think there's anything else I can do on this right now, so I'm going to close it.