Несмотря на ошибку контроллера, мои тесты по-прежнему проходят, при посещении редактируемого URL правильно отображается ошибка Почему это так? - PullRequest
0 голосов
/ 10 января 2011

У меня есть контроллер Rails, где я случайно определил метод edit внутри метода create.

Мой контроллер с ошибкой:

class UsersController < ApplicationController
...
  def create
    @user = User.new(params[:user])
    ...

    def edit
      @user = User.find(params[:id])
      @title = "Edit user"
      @check = "BORK" # something I added for testing the rendered output
    end
  end
end

Пример теста;

it "should have the right title" do
  get :edit, :id => @user
  response.should have_selector('title', :content => 'Edit user')
end

Поэтому, когда я запускаю тесты (я использую rspec) и выводлю response.body, шаблон User edit.html.erb отображается правильно; все переменные экземпляра видны. Итак, все тесты пройдены.

Посещение URL 'edit' правильно показывает ошибку; шаблон использует переменную экземпляра @user, и он не установлен правильно. Конечно, исправление контроллера исправляет ошибку.

Я не понимаю, почему тесты проходят вообще, и почему в тесте все значения переменных экземпляра видны?

Мой инстинкт подсказывает, что это проблема масштаба? Что-то о том, что @user является переменной экземпляра, и что в тестах он установлен в рамках теста, но в моем контроллере он находится в рамках внутреннего метода edit? Но как тест находит метод «редактирования»? В какой области существует этот внутренний метод редактирования?

1 Ответ

3 голосов
/ 10 января 2011

Вы должны понимать, что конструкция def - это столько же исполняемого кода, сколько и оператор if.Это не недопустимо , чтобы поместить его в другой метод, но он не будет запущен, пока не будет вызван внешний метод:

>> class Foo
>>   def foo
>>     def bar
>>     end
>>   end
>> end
=> nil 
>> Foo.instance_methods(false)
=> ["foo"] 
>> Foo.new.foo
=> nil 
>> Foo.instance_methods(false)
=> ["foo", "bar"] 

Причина, по которой в браузере произошла ошибка, заключалась в том, что Railsперезагружает все (большинство) ваших классов каждый запрос.Таким образом, даже если бы вы посетили действие create - что привело бы к определению метода edit - следующий запрос выгрузил бы его снова.

Однако в тестовой среде, если более ранний тесттогда он вызвал действие create, которое определило бы действие edit для будущих тестов.Вы бы увидели другой результат, если бы ваши тесты выполнялись в другом порядке (что само по себе делает плохой идеей полагаться на это).

Обычно, конечно, это совсем не то, что вам нужно, поэтомупросто очистите его и двигайтесь дальше:)

...