2016-12-11 2 views
0

Я пишу несколько тестов для веб-приложения, а один из контроллеров вызывает resolve на объекте Scope, который возвращает слегка измененную область. В тесте я хотел бы заглушить этот метод, чтобы вернуть исходную область (передан как параметр в Scope.initialize).Как получить доступ к переменным экземпляра объекта во время stubbing?

Scope объект

class Scope 

    def initialize(scope) 
    @scope = scope 
    end 

    def resolve 
    # Return a modified scope. 
    end 
end 

Контроллер

class FooController < ApplicationController 

    def show 
    foos = Scope.new(Foo.some_foos).resolve 
    respond_with foos 
    end 
end 

Испытание

it "does something" do 
    allow_any_instance_of(Scope).to receive(:resolve).and_return(???.scope) 
    get :show 
    # Do some assertions. 
end 

Что мне нужно, чтобы положить где ???, чтобы заглушить метод resolve в любом экземпляре Scope, чтобы вернуть исходный объем, с которым он был создан?

Я использую Rspec 3.4.2.

ответ

1

Сначала вы хотите создать читателя атрибут Scope, так что вы можете получить доступ к @scope без использования instance_variable_get:

class Scope 

    attr_reader :scope 

    def initialize(scope) 
    @scope = scope 
    end 

    def resolve 
    # Return a modified scope. 
    end 
end 

Если вы используете реализацию блока приемника передается в качестве первого арг:

allow_any_instance_of(Scope).to receive(:resolve) do |s| 
    s.scope 
end 

Однако использование allow_any_instance_of сильно обескуражено и обычно является признаком того, что ваши тесты слишком много вызывают слишком много в том, как ваши контроллеры выполняют свою работу, а не на самом деле testing their behavior in a future proof way.

Я бы вместо этого использовал единичный тест, который проверяет Scope и запрашивает спецификации, которые тестируют контроллер в сочетании с спецификациями характеристик. Вот как я тестирую приложения, которые используют Pundit, и является надежной стратегией.

Смежные вопросы