I've got something like this:
# post_observer.rb
after_create
# ...stuff
Delayed::Job.enqueue(PostSharer.new(post, post.user))
end
...
# post_sharer.rb
class PostSharer < Struct.new(:post, user)
def perform
# Delayed::Job calls .perform on the object passed into enqueue
end
end
# post_controller_spec.rb
it "shares the post" do
PostSharer.expects(:new).once
lambda { do_post }.should change(Delayed::Job, :count).by(1)
end
...
This fails due to the expectation put on PostSharer receiving .new ---
if I
remove that, then it all works fine... And if I look at the test
database,
Delayed::Job has created a job for PostSharer, so it is all working as
desired.. I just wanted to take it a step further and ensure that the
right
class is being instantiated. I am assuming this is because setting an
expectation on new is somehow changing the structure of the class and
confusing
delayed job? Maybe because it's a struct?
1) PostsController creating a post sharing shares when it should
Failure/Error: post :create, { :submit_action => submit_type.to_s,
:post => new_post(post_attributes).attributes }
ArgumentError:
Cannot enqueue items which do not respond to perform
# ./app/observers/post_observer.rb:12:in `after_create'
# ./app/models/post.rb:156:in `set_state_to_open_for_free_requests'
# ./app/controllers/posts_controller.rb:39:in `create'
# ./spec/controllers/post_controller_spec.rb:8:in `do_post'
# ./spec/controllers/post_controller_spec.rb:77
# ./spec/controllers/post_controller_spec.rb:75
Patrick J. Collins
http://collinatorstudios.com
on 2011-12-02 02:34
on 2011-12-02 05:46
On Dec 1, 2011, at 6:34 PM, Patrick J. Collins wrote: > > # post_controller_spec.rb > This fails due to the expectation put on PostSharer receiving .new --- if I > remove that, then it all works fine... And if I look at the test database, > Delayed::Job has created a job for PostSharer, so it is all working as > desired.. You could automate "if I look at the test database" bit as part of the test. > I just wanted to take it a step further and ensure that the right > class is being instantiated. Wouldn't the record in the database be enough? If not, you could do this: Delayed::Job.expects(:enqueue).with(PostSharer.new(post, post.user)) > I am assuming this is because setting an > expectation on new is somehow changing the structure of the class and confusing > delayed job? Maybe because it's a struct? In rspec-mocks, when you say Klass.stub(:new), Klass.new returns a proxy, not an instance of the Klass. I'm pretty sure the same is true of mocha. Cheers, David
on 2011-12-02 07:21
> In rspec-mocks, when you say Klass.stub(:new), Klass.new returns a proxy, not > an instance of the Klass. I'm pretty sure the same is true of mocha. Ok-- I guess I wasn't realizing that Klass.expects(:new) was actually stubbing the class.. I was thinking it was doing something like making a duplicate of the initialize method (making it something like "_initialize") and then overwriting the real initialize method with something that calls _initialize but also sets a flag to indicate that .new had been called... So that's apparently not quite the case? In any event, after reading what you wrote I got my test to pass by doing: PostSharer.expects(:new).once.returns stub("Fake Post Sharer", :perform => true) So this way delayed_job still can call perform on the fake object and everyone is happy (especially me). Patrick J. Collins http://collinatorstudios.com
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.