Rspec 3, wie man Flash-Nachrichten testet

81

Ich möchte die Aktion des Controllers und das Vorhandensein von Flash-Nachrichten mit rspec testen.

Aktion :

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

spec :

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

Aber ich habe einen Fehler:

Failure/Error: expect(flash[:success]).to be_present
   expected `nil.present?` to return true, got false
Mike Andrianov
quelle

Antworten:

67

Sie testen auf das Vorhandensein von flash[:success], aber in Ihrem Controller verwenden Sieflash[:notice]

Rabusmar
quelle
Oh, sorry, ich bin gerade hierher gerutscht. Gleicher Fehler mit Flash [: Hinweis]
Mike Andrianov
3
In diesem Fall liegt das Problem wahrscheinlich an Ihrem Controller-Code und / oder Ihren Testdaten. Versuchen Sie, die sich ändern expect(flash[:notice])zu expect(flash[:alert]), und wenn der Test dann wohl passiert , es ist nur , dass der Test E - Mail existiert nicht.
Rabusmar
48

Der beste Weg, um Flash-Nachrichten zu testen, bietet das Sollte- Juwel.

Hier sind drei Beispiele:

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

Wenn Sie mehr am Inhalt der Flash-Nachrichten interessiert sind, können Sie Folgendes verwenden:

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

oder

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

Ich würde davon abraten, nach einer bestimmten Nachricht zu suchen, es sei denn, diese Nachricht ist kritisch und / oder ändert sich nicht oft.

Mugur 'Bud' Chirica
quelle
5

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

Das .nowsollte direkt am angerufen werden set_flash.

Die Verwendung set_flashmit dem nowQualifizierer und die Angabe nownach anderen Qualifizierern ist nicht mehr zulässig.

Sie möchten nowsofort danach verwenden set_flash. Zum Beispiel:

# 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
Killerkiara
quelle
0

Der andere Ansatz besteht darin, die Tatsache, dass ein Controller über Flash-Meldungen verfügt, wegzulassen und stattdessen einen Integrationstest zu schreiben. Auf diese Weise erhöhen Sie die Wahrscheinlichkeit, dass Sie den Test nicht ändern müssen, wenn Sie diese Nachricht mit JavaScript oder auf andere Weise anzeigen.

Siehe auch https://stackoverflow.com/a/13897912/2987689

Artur Beljajev
quelle