Reputation: 1237
When a user im trying to unfollow doesn't exist I throw an exception that sets a flash error message and redirects the user back to the page they were on.
All the access to the twitter gem is handled by the TwitterManager class which is a regular ruby class that extend ActiveModel::Naming to enable the mock_model.
Now Im having a real hard time figuring out how this should be tested. The code below works but feels very wrong. The only way I could stub the twitter.unfollow method was with controller.send(:twitter).stub(:unfollow).and_raise(Twitter::Error::NotFound.new("", {}))
I tried using TwitterManager.any_instance.stub(:unfollow) but that did obviously not do what I thought it would do.
How can I make this better? What things have I totally misunderstood?
describe TwitterController do
before(:each) do
controller.stub(:twitter).and_return(mock_model("TwitterManager", unfollow: true, follow: true))
end
it "unfollows a user when given a nickname" do
@request.env['HTTP_REFERER'] = '/followers'
post 'unfollow', id: "existing_user"
response.should redirect_to followers_path
end
describe "POST 'unfollow'" do
it "does not unfollow a user that does not exist" do
controller.send(:twitter).stub(:unfollow).and_raise(Twitter::Error::NotFound.new("", {}))
@request.env['HTTP_REFERER'] = '/followers'
post 'unfollow', id: "non_existing_user"
flash[:error].should_not be_nil
flash[:error].should have_content("not found, could not unfollow")
response.should redirect_to followers_path
end
end
def unfollow
begin
twitter.unfollow(params[:id])
respond_to do |format|
format.html { redirect_to :back, notice: "Stopped following #{params[:id]}" }
end
rescue Twitter::Error::NotFound
redirect_to :back, :flash => { error: "User #{params[:id]} not found, could not unfollow user" }
end
end
[ more code ]
private
def twitter
twitter_service ||= TwitterFollower.new(current_user)
end
Rspec 2.8.0 Rails 3.2.0
Upvotes: 0
Views: 570
Reputation: 14983
You could clean it up a little by saving the mock TwitterManager
as an instance variable in the before
block and stubbing directly on that object:
describe TwitterController do
before(:each) do
@twitter = mock_model("TwitterManager", unfollow: true, follow: true)
controller.stub(:twitter).and_return(@twitter)
end
# ...
describe "POST 'unfollow'" do
it "does not unfollow a user that does not exist" do
@twitter.stub(:unfollow).and_raise(Twitter::Error::NotFound.new("", {}))
# ...
end
end
end
But I wouldn't say what you're doing is "very wrong" :-)
Upvotes: 1