Почему у контроллера должен быть метод assign_to, у которого нет доступа к переменной экземпляра? - PullRequest
2 голосов
/ 12 сентября 2011

Для моего приложения на Rails 3 я использую FactoryGirl вместе с контекстом musta (1.0.0.beta1) и средствами сопоставления (1.0.0.beta3) для своих функциональных тестов. Моя проблема: в приведенном ниже примере кода тест assign_to не проходит, потому что @user - к моему удивлению - оказывается равным нулю. Во внешнем блоке настройки @user назначается действительный экземпляр модели, но из-за оператора should assign_to переменная экземпляра недоступна. Почему это так и как правильно написать этот тест?

class UsersControllerTest < ActionController::TestCase
  context "as admin" do
    setup do
      @user = Factory.create(:user)
    end

    context "getting index" do
      setup do
        get :index
      end

      should assign_to(:users).with([@user])
    end
end

Ответы [ 3 ]

0 голосов
/ 20 февраля 2012

Я обнаружил, что передача значения как черного чудесным образом работает. Однако после того, как мы покопались в фактическом коде AssignToMatcher , кажется, что не имеет смысла, почему метод параметра не будет работать, в то время как метод блока будет.

Ради +250 представителей, которые я вкладываю в это, мне все равно хотелось бы получить ответ, объясняющий, почему метод param не работает (и как его исправить), но до тех пор, по крайней мере, я есть обходной путь.

@ dblp1, надеюсь, это работает и для вас. Вот пример, специфичный для вашего кода:

class UsersControllerTest < ActionController::TestCase
  context "as admin" do
    setup do
      @user = Factory.create(:user)
    end

    context "getting index" do
      setup do
        get :index
      end

      should assign_to(:users).with { [@user] }
    end
  end
end
0 голосов
/ 26 февраля 2012

(я вставляю в качестве ответа, поскольку он довольно длинный)

Я немного высмеял ваш тест и проверил, какие результаты были пройдены.

Довольно интересно, когда я вызываю совпадение@post=null (как я полагаю в вашем случае).Проблемы, которые, я думаю (после некоторого времени исследования), связаны с порядком вызова блока setup do и тем фактом, что переменные, определенные в одном контексте, не видны во вложенном контексте.

измененоclass

context "as admin" do
 setup do
   @post = Post.new
   puts "Step 1 - inside setup do"
   puts @post.class
 end
 puts "Step 2 - outside setup do 1"
 puts @post.class

 context "getting index" do
   setup do
     get :index
   end
   puts "Step 3 - calling shoulda"
   puts @post.class
   should assign_to(:posts).with([@post])
   #should assign_to(:posts).with  { [@post] }
   end
end

И результаты в консоли

ruby -I test test/functional/posts_controller_test.rb
Step 2 - outside setup do 1
NilClass
Step 3 - calling shoulda
NilClass
Loaded suite test/functional/posts_controller_test
Started
Step 1 - inside setup do
Post

Таким образом, цикл установки вызывается в конце (а не в начале), а затем передается в Nil при передаче вmatcher.

Даже если я удаляю первое setup do, это не очень хорошо работает.

Step 1 - inside setup do
Post
Step 2 - outside setup do 1
Post
Step 3 - calling shoulda
NilClass

Наконец, помещаем сообщение во внутренний контекст

Step 3 - calling shoulda
Post

Если вы вызываете @user = Factory.create(:user) непосредственно внутри контекста «получения индекса», я думаю, что это сработает.

0 голосов
/ 29 сентября 2011

Когда вы работаете с индексами, вы должны использовать множественное число переменной экземпляра.

@users вместо @user

Вы также должны заполнять его как массив.

Наконец, спички должны должны начинаться с «это» и содержаться в фигурных скобках, по крайней мере, в мире RSpec, что я и использую.Не уверен, что это так с Test :: Unit или сработает ли указанное выше форматирование.

Попробуйте что-то подобное.

class UsersControllerTest < ActionController::TestCase
  context "as admin" do
    setup do
      @user = Factory.create(:user)
    end

    context "getting index" do
      setup do
        @users = Array.new(3) { Factory(:user) }
        get :index
      end

      it { should assign_to(:users).with(@users) }
    end
end
...