Question

Supposons que vous ayez un ActiveRecord :: Observer dans l'une de vos applications Ruby on Rails - comment tester cet observateur avec rSpec ?

Était-ce utile?

La solution

Vous êtes sur la bonne voie, mais j'ai rencontré un certain nombre d'erreurs de message inattendues et frustrantes lors de l'utilisation de rSpec, d'observateurs et d'objets fictifs.Lorsque je teste les spécifications de mon modèle, je ne veux pas avoir à gérer le comportement des observateurs dans mes attentes de message.

Dans votre exemple, il n'existe pas de très bon moyen de spécifier "set_status" sur le modèle sans savoir ce que l'observateur va y faire.

C'est pourquoi j'aime utiliser le Plugin "Pas de voyeurs". Compte tenu de votre code ci-dessus et en utilisant le plugin No Peeping Toms, je spécifierais le modèle comme ceci :

describe Person do 
  it "should set status correctly" do 
    @p = Person.new(:status => "foo")
    @p.set_status("bar")
    @p.save
    @p.status.should eql("bar")
  end
end

Vous pouvez spécifier le code de votre modèle sans avoir à craindre qu'un observateur vienne écraser votre valeur.Vous le spécifieriez séparément dans person_observer_spec comme ceci :

describe PersonObserver do
  it "should clobber the status field" do 
    @p = mock_model(Person, :status => "foo")
    @obs = PersonObserver.instance
    @p.should_receive(:set_status).with("aha!")
    @obs.after_save
  end
end 

Si vous voulez VRAIMENT VRAIMENT tester la classe couplée Model et Observer, vous pouvez le faire comme ceci :

describe Person do 
  it "should register a status change with the person observer turned on" do
    Person.with_observers(:person_observer) do
      lambda { @p = Person.new; @p.save }.should change(@p, :status).to("aha!)
    end
  end
end

99 % du temps, je préfère tester les spécifications avec les observateurs désactivés.C'est juste plus facile ainsi.

Autres conseils

Clause de non-responsabilité:Je n'ai jamais fait cela sur un site de production, mais il semble qu'un moyen raisonnable serait d'utiliser des objets fictifs, should_receive et amis, et invoquez des méthodes directement sur l'observateur

Étant donné le modèle et l'observateur suivants :

class Person < ActiveRecord::Base
  def set_status( new_status )
    # do whatever
  end
end

class PersonObserver < ActiveRecord::Observer
  def after_save(person)
    person.set_status("aha!")
  end
end

J'écrirais une spécification comme celle-ci (je l'ai exécutée et elle réussit)

describe PersonObserver do
  before :each do
    @person = stub_model(Person)
    @observer = PersonObserver.instance
  end

  it "should invoke after_save on the observed object" do
    @person.should_receive(:set_status).with("aha!")
    @observer.after_save(@person)
  end
end

no_peeping_toms est désormais un joyau et peut être trouvé ici : https://github.com/patmaddox/no-peeping-toms

Si vous souhaitez tester que l'observateur observe le bon modèle et reçoit la notification comme prévu, voici un exemple utilisant RR.

votre_modèle.rb :

class YourModel < ActiveRecord::Base
    ...
end

votre_modèle_observer.rb :

class YourModelObserver < ActiveRecord::Observer
    def after_create
        ...
    end

    def custom_notification
        ...
    end
end

votre_modèle_observer_spec.rb :

before do
    @observer = YourModelObserver.instance
    @model = YourModel.new
end

it "acts on the after_create notification"
    mock(@observer).after_create(@model)
    @model.save!
end

it "acts on the custom notification"
    mock(@observer).custom_notification(@model)
    @model.send(:notify, :custom_notification)
end
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top