Rspec 3如何测试 flash 消息

我想测试控制器的行动和闪光消息的存在与 rspec。

行动 :

def create
user = Users::User.find_by_email(params[:email])
if user
user.send_reset_password_instructions
flash[:success] = "Reset password instructions have been sent to #{user.email}."
else
flash[:alert] = "Can't find user with this email: #{params[:email]}"
end


redirect_to root_path
end

规格 :

describe "#create" do
it "sends reset password instructions if user exists" do
post :create, email: "email@example.com"
expect(response).to redirect_to(root_path)
expect(flash[:success]).to be_present
end
...

但是我有一个错误:

Failure/Error: expect(flash[:success]).to be_present
expected `nil.present?` to return true, got false
59064 次浏览

You are testing for the presence of flash[:success], but in your controller you are using flash[:notice]

The best way to test flash messages is provided by the shoulda gem.

Here are three examples:

expect(controller).to set_flash
expect(controller).to set_flash[:success]
expect(controller).to set_flash.now[:alert].to(/are not valid/)

If you are more interested in the content of the flash messages you can use this:

expect(flash[:success]).to match(/Reset password instructions have been sent to .*/)

or

expect(flash[:alert]).to match(/Can't find user with this email: .*/)

I would advise against checking for a specific message unless that message is critical and/or it does not change often.

The another approach is to leave out the fact that a controller has flash messages and write an integration test instead. This way you increase chances that you will not need to alter the test once you decide to show that message using JavaScript or by some other way.

See also https://stackoverflow.com/a/13897912/2987689

With: gem 'shoulda-matchers', '~> 3.1'

The .now should be called directly on the set_flash.

Using set_flash with the now qualifier and specifying now after other qualifiers is no longer allowed.

You'll want to use now immediately after set_flash. For instance:

# Valid
should set_flash.now[:foo]
should set_flash.now[:foo].to('bar')


# Invalid
should set_flash[:foo].now
should set_flash[:foo].to('bar').now