web-dev-qa-db-fra.com

Existe-t-il un moyen de stub une méthode d'un module inclus avec Rspec?

J'ai un module qui est inclus dans un autre module, et ils implémentent tous les deux la même méthode. Je voudrais stub la méthode du module inclus, quelque chose comme ceci:

module M
  def foo
    :M
  end
end

module A
  class << self
    include M

    def foo
      super
    end
  end
end

describe "trying to stub the included method" do
  before { allow(M).to receive(:foo).and_return(:bar) }

  it "should be stubbed when calling M" do
    expect(M.foo).to eq :bar
  end

  it "should be stubbed when calling A" do
    expect(A.foo).to eq :bar
  end
end

Le premier test réussit, mais le second génère:

Failure/Error: expect(A.foo).to eq :bar

   expected: :bar
        got: :M

Pourquoi le talon ne fonctionne-t-il pas dans ce cas? Existe-t-il un moyen différent d'y parvenir?

Merci!

-------------------------------------MISE À JOUR------------ ----------------------

Merci! l'utilisation de allow_any_instance_of (M) a résolu celui-ci. Ma prochaine question est - que se passe-t-il si j'utilise le préfixe et non l'inclusion? voir le code suivant:

module M
  def foo
    super
  end
end

module A
  class << self
    prepend M

    def foo
      :A
    end
  end
end

describe "trying to stub the included method" do
  before { allow_any_instance_of(M).to receive(:foo).and_return(:bar) }

  it "should be stubbed when calling A" do
    expect(A.foo).to eq :bar
  end
end 

Cette fois, l'utilisation de allow_any_instance_of (M) entraîne une boucle infinie. pourquoi donc?

27
user3775153

Notez que vous ne pouvez pas appeler directement M.foo! Votre code ne semble fonctionner que parce que vous vous êtes moqué de M.foo Pour renvoyer :bar.

Lorsque vous ouvrez A métaclasse (class << self) Pour inclure M, vous devez vous moquer de toute instance de M, c'est-à-dire ajouter à votre before bloquer:

allow_any_instance_of(M).to receive(:foo).and_return(:bar)

module M
  def foo
    :M
  end
end

module A
  class << self
    include M

    def foo
      super
    end
  end
end

describe "trying to stub the included method" do
  before do
    allow(M).to receive(:foo).and_return(:bar)
    allow_any_instance_of(M).to receive(:foo).and_return(:bar)
  end


  it "should be stubbed when calling M" do
    expect(M.foo).to eq :bar
  end

  it "should be stubbed when calling A" do
    expect(A.foo).to eq :bar
  end
end
32
mdemolin