Чрезвычайно странный 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
).