Question

J'écris un scénario thats rspec défaut avec:

 (#<User:0x1056904f0>).update_attributes(#<RSpec::Mocks::ArgumentMatchers::AnyArgMatcher:0x105623648>)
     expected: 1 time
     received: 0 times

users_controller_spec.rb:

describe "Authenticated examples" do
  before(:each) do
    activate_authlogic
    @user = Factory.create(:valid_user)
    UserSession.create(@user)
  end

describe "PUT update" do
    it "updates the requested user" do
      User.stub!(:current_user).and_return(@user)
      @user.should_receive(:update_attributes).with(anything()).and_return(true)
      put :update, :id => @user , :current_user => {'email' => 'Trippy'}
      puts "Spec Object Id : " + "#{@user.object_id}"
 end

users_controller.rb:

def update
  @user = current_user
  puts "Controller Object ID is : " + "#{@user.object_id}"

  respond_to do |format|
    if @user.update_attributes(params[:user])
      format.html { redirect_to(root_url, :notice => 'Successfully updated profile.') }
      format.xml  { head :ok }
    else
      format.html { render :action => "edit" }
      format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
    end
  end
end

user.rb - usines

Factory.define :valid_user, :class => User do |u|
  u.username "Trippy"
  u.password "password"
  u.password_confirmation "password"
  u.email "elephant@gmail.com"
  u.single_access_token "k3cFzLIQnZ4MHRmJvJzg"
  u.id "37"
end
Était-ce utile?

La solution

méthodes d'assistance standard de Authlogic comme current_user n'appellent User.find directement. Je crois qu'il fait current_user_session.user, où current_user_session appelle UserSession.find, de sorte que vous n'êtes pas appeler directement User.find. Vous pourriez faire une chaîne de fantaisie stubbing là, mais ma suggestion est juste d'ajouter ceci à votre spec du contrôleur au lieu de ce que vous êtes actuellement stubbing:

stub!(:current_user).and_return(@user)

Dans RSpec2 vous pourriez avoir à faire

controller.stub!(:current_user).and_return(@user)

Edit: Cela devrait être votre dossier complet de spécifications:

describe "Authenticated examples" do
  before(:each) do
    activate_authlogic
    @user = Factory.create(:valid_user)
    UserSession.create(@user)
  end

describe "PUT update" do

  describe "with valid params" do
    it "updates the requested user" do
      stub!(:current_user).and_return(@user)
      @user.should_receive(:update_attributes).with(anything()).and_return(true)
      put :update, :id => @user , :current_user => {'email' => 'Trippy'}
    end
 end

Autres conseils

Je pense que vous confondez avec les talons attentes de message. La ligne

User.should_receive(:find)

indique Rspec attendre le modèle de l'utilisateur pour recevoir un message de recherche. Attendu que:

User.stub!(:find)

remplace la méthode de recherche pour que le test peut passer. Dans votre exemple, la chose que vous testez est de savoir si update_attributes est appelé avec succès, de sorte que doit être là où l'attente du message passe, et le travail de tous les autres codes de test est juste de mettre en place les conditions préalables.

Essayer le remplacement de cette ligne avec:

User.stub!(:find).and_return(@user)

Notez que find renvoie l'objet, non seulement son id. Notez également que find ici sur stubbing ne sert qu'à accélérer les choses. Comme l'écrit l'exemple obtient par should_receive(:find) avec succès, et que se passe parce que vous utilisez les usines pour créer des utilisateurs dans la base de données de test. Vous pouvez prendre le bout dehors et le test devrait fonctionner, mais au prix de frapper la base de données.

Une autre astuce: si vous essayez de comprendre pourquoi un test de contrôleur ne fonctionne pas, il est parfois utile de savoir si elle est bloquée par les filtres before. Vous pouvez vérifier cela avec:

controller.should_receive(:update)

Si cela échoue, l'action update n'est pas atteint, probablement parce qu'un filtre before a réorienté la demande.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top