Чрезвычайно странный ruby ​​'||=' и rspec удваивают поведение

Запуск следующего rspec Версии драгоценных камней:

  * rspec (2.14.1)
  * rspec-core (2.14.7)
  * rspec-expectations (2.14.5)
  * rspec-mocks (2.14.6)
  * rspec-rails (2.14.1)

А также octokit 2.7.1

Учитывая следующее в spec/support/octokit.rb:

# This support package contains modules for octokit mocking

module OctokitHelper
  def mock_pull_requests_for_org org
     mock_org_repos(org).map do |repo| 
      mock_pull_requests repo 
    end.flatten
  end
  def mock_org_repos org
    @@repos ||= [
      double('Sawyer::Resource', name: 'repo 1'),
      double('Sawyer::Resource', name: 'repo 2')
    ]
    Octokit.stub(:org_repos) { |org=org| @@repos }
    @@repos
  end
  def mock_pull_requests repo, gh_handle=nil
    @@pulls ||= [
      double('Sawyer::Resource', title: 'pr 1'),
      double('Sawyer::Resource', title: 'pr 2')
    ]
    Octokit.stub(:pull_requests) { |repo| @@pulls }
    @@pulls 
  end
end

RSpec.configure do |config|
  config.include OctokitHelper 
end

Всякий раз, когда я пытаюсь позвонить mock_org_repos первый раз из спецификации, @@repos.first.name является repo 1, Второй раз, @@repos.first.name выдает действительно странную ошибку:

  1) StudentsController GET #submissions renders pull requests template
     Failure/Error: get :submissions, student_id: 2
       Double "Sawyer::Resource" received unexpected message :name with (no args)

Пример моего использования mock_org_repos:

require 'spec_helper'

describe StudentsController do
  describe 'GET #submissions' do
    before do
      @user = FactoryGirl.create(:instructor)
      @user.stub(:is_instructor?) { true }
      @submissions = mock_pull_requests_for_org ENV['GA_ORG_NAME']
      controller.stub(:current_user) { @user }
      get :submissions, student_id: 2
    end
    it 'assigns @submissions' do
      assigns(:submissions).should == @submissions
    end
    it 'renders pull requests template' do
      response.should render_template 'submissions'
    end
  end
end

2 ответа

Решение

Большое спасибо rsofaer, который предоставил мне свою вторую пару глаз, чтобы решить эту проблему, я хотел бы указать на очень очевидную проблему:

Методы, заданные для двойников, "очищаются" каждый раз, когда запускаются примеры, когда на заглушки ссылаются через переменные класса.

Это очень четкое объяснение того, как RSpec работает под прикрытием.

Я предполагаю, что один из двойников, которые вы создали в mock_pull_requests с тем же именем отправляется :name, но вы можете проверить это, убедившись, что ваши двойники имеют уникальные имена (т.е. первый аргумент double).

Другие вопросы по тегам