RSpec permettre/attendre vs juste attendre et/retour

Dans RSpec, plus précisément de la version >= 3, quelle est la différence entre:

  • en utilisant allow pour définir les attentes des messages avec des paramètres qui renvoient des doublures de test, puis en utilisant expect pour faire une assertion sur le retour de l'essai de double
  • Juste à l'aide de expect pour configurer l'attente avec les paramètres et retourner le test double

ou est-ce juste de la sémantique? Je sais que fournir / spécifier une valeur de retour avec expect la syntaxe de RSpec se moque de 2.13, mais aussi loin que je peux voir, la syntaxe a changé dans RSpec mocks 3 utiliser allow.

cependant, dans l'exemple de code (passant) ci-dessous, en utilisant allow/expect ou expect/and_return semble générer le même résultat. Si une syntaxe était favorisée par rapport à une autre, peut-être que j'aurais pu m'attendre à ce qu'il y ait une sorte de notice d'imprécision, mais puisqu'il n'y en a pas, il semblerait que les deux syntaxes soient considérées valide:

class Foo
  def self.bar(baz)
    # not important what happens to baz parameter
    # only important that it is passed in
    new
  end

  def qux
    # perform some action
  end
end

class SomethingThatCallsFoo
  def some_long_process(baz)
    # do some processing
    Foo.bar(baz).qux
    # do other processing
  end
end

describe SomethingThatCallsFoo do
  let(:foo_caller) { SomethingThatCallsFoo.new }

  describe '#some_long_process' do
    let(:foobar_result) { double('foobar_result') }
    let(:baz) { double('baz') }

    context 'using allow/expect' do
      before do
        allow(Foo).to receive(:bar).with(baz).and_return(foobar_result)
      end

      it 'calls qux method on result of Foo.bar(baz)' do
        expect(foobar_result).to receive(:qux)
        foo_caller.some_long_process(baz)
      end
    end

    context 'using expect/and_return' do
      it 'calls qux method on result of Foo.bar(baz)' do
        expect(Foo).to receive(:bar).with(baz).and_return(foobar_result)
        expect(foobar_result).to receive(:qux)
        foo_caller.some_long_process(baz)
      end
    end
  end
end

Si j'ai délibérément de faire les tests échouent en changeant le passé -baz paramètre dans l'attente d'un test en double, les erreurs sont à peu près la même:

  1) SomethingThatCallsFoo#some_long_process using allow/expect calls quux method on result of Foo.bar(baz)
     Failure/Error: Foo.bar(baz).qux
       <Foo (class)> received :bar with unexpected arguments
         expected: (#<RSpec::Mocks::Double:0x3fe97a0127fc @name="baz">)
              got: (#<RSpec::Mocks::Double:0x3fe97998540c @name=nil>)
        Please stub a default value first if message might be received with other args as well.
     # ./foo_test.rb:16:in `some_long_process'
     # ./foo_test.rb:35:in `block (4 levels) in <top (required)>'

  2) SomethingThatCallsFoo#some_long_process using expect/and_return calls quux method on result of Foo.bar(baz)
     Failure/Error: Foo.bar(baz).qux
       <Foo (class)> received :bar with unexpected arguments
         expected: (#<RSpec::Mocks::Double:0x3fe979935fd8 @name="baz">)
              got: (#<RSpec::Mocks::Double:0x3fe979cc5c0c @name=nil>)
     # ./foo_test.rb:16:in `some_long_process'
     # ./foo_test.rb:43:in `block (4 levels) in <top (required)>'

donc, y a-t-il des différences réelles entre ces deux tests, que ce soit dans le résultat ou l'intention exprimée, ou s'agit-il seulement de sémantique et/ou de préférence personnelle? Doit allow/expect être utilisé sur expect/and_return en général comme il semble que c'est la syntaxe de remplacement, ou sont chacun destinés à être utilisés dans des scénarios de test spécifiques?

mise à Jour

Après la lecture de réponse de Mori's, j'ai commenté l' Foo.bar(baz).qux ligne à partir de l'exemple de code ci-dessus, et a obtenu les erreurs suivantes:

  1) SomethingThatCallsFoo#some_long_process using allow/expect calls qux method on result of Foo.bar(baz)
     Failure/Error: expect(foobar_result).to receive(:qux)
       (Double "foobar_result").qux(any args)
           expected: 1 time with any arguments
           received: 0 times with any arguments
     # ./foo_test.rb:34:in `block (4 levels) in <top (required)>'

  2) SomethingThatCallsFoo#some_long_process using expect/and_return calls qux method on result of Foo.bar(baz)
     Failure/Error: expect(Foo).to receive(:bar).with(baz).and_return(foobar_result)
       (<Foo (class)>).bar(#<RSpec::Mocks::Double:0x3fc211944fa4 @name="baz">)
           expected: 1 time with arguments: (#<RSpec::Mocks::Double:0x3fc211944fa4 @name="baz">)
           received: 0 times
     # ./foo_test.rb:41:in `block (4 levels) in <top (required)>'
  • allow spec échoue parce que le foobar_result double n'arrive jamais à tenir dans pour la suite de Foo.bar(baz), et donc jamais a #qux appelé
  • expect défaillance des spécifications au point de Foo ne jamais recevoir .bar(baz) donc nous n'arrivons même pas au point d'interroger le foobar_result double

sens: c'est pas juste un changement de syntaxe, et que expect/and_return a un but différent de allow/expect. J'aurais vraiment dû vérifier l'endroit le plus évident: le RSpec Mocks README, plus précisément les sections suivantes:

25
demandé sur Community 2015-01-18 06:41:16
la source

1 ответов

Voir l'article classique les moqueries ne sont pas des Chaumes. allow fait un talon tout expect fait une maquette. allow permet à un objet de retourner X au lieu de tout ce qu'il retournerait sans avoir été soumis, et expect est un allow les plus une attente d'un État ou d'un événement. Quand vous écrivez

allow(Foo).to receive(:bar).with(baz).and_return(foobar_result)

... vous dites à l'environnement spec de modifier Foo retour foobar_result quand il reçoit :barbaz. Mais quand vous Ecrire

expect(Foo).to receive(:bar).with(baz).and_return(foobar_result) 

... vous êtes en train de faire la même chose, en plus de raconter, de la spécification à l'échec à moins queFoo reçoit :barbaz.

voir la différence, essayez les deux dans les exemples où Foo recevoir :barbaz.

63
répondu Mori 2015-01-18 16:39:35
la source

Autres questions sur