2013-05-29 1 views
0

Работая над выполнением главы 10 учебного пособия Rails, которое относится к тестированию разбиения на страницы микропоставок, я не могу понять, почему мои тесты ломаются, когда я их делаю с before(:all) и after(:all) как ниже. Даже просто меняя его на before(:each), он работает, поэтому это не переменная экземпляра. (хотя я могу также заставить его работать, не используя экземпляр, и создать user, предоставленный let)не уверен, почему изменение до того, как все разрывает этот тест

Я просто пытаюсь сделать это надлежащим образом. Выполнение этого раз (то есть, :all) кажется правильным для этого. Что мне не хватает?

Я пробовал stop_and_open_page - он не показывает никаких микропотоков, когда я использую :all, только в противном случае (с :each). Однако, проверяя либо мою переменную экземпляра, либо user (при попытке этого сделать с let) с binding.pry в консоли - она ​​имеет микросообщения все время, даже когда я указываю :all.

Я думаю, что это связано с тем, что я не загружаю ассоциацию, когда использую :all, но я не могу придумать причину, так как она работает иначе на сайте образца и в тестах, когда не используется :all.

Любые идеи?

P.S. У меня есть побочный вопрос: у меня есть отношение, установленное в моей модели User, например, has_many :microposts, dependent: :destroy, но когда я делаю эти тесты с помощью метода переменных экземпляра, приведенного ниже, я должен явно называть delete_all на микропостах, в противном случае они остаются в тестовом db после (даже если пользователь удаляется). Я пропустил что-то там очевидное или каскадное уничтожение не работает, когда пользователь создан через Factory Girl?

UPDATE: Благодаря @Jesper я поймал причину, по которой after (: all) не удалял связанные микропосты. Код обновлен, чтобы отразить это.

subject { page } 

let(:user) { FactoryGirl.create(:user) } 
before { valid_signin user } 

... 

describe "micropost pagination" do 

    before(:all) do 
    @user_with_many_posts = FactoryGirl.create(:user, email: "[email protected]") 
    @user_with_many_posts.save 
    31.times { FactoryGirl.create(:micropost, user: @user_with_many_posts) } 
    valid_signin @user_with_many_posts 
    visit root_path 
    end 

    after(:all) do 
    @user_with_many_posts.destroy 
    end 

    it { should have_selector('div.pagination') } 

    it "should list each micropost" do 
    @user_with_many_posts.microposts.paginate(page: 1).each do |mp| 
     expect(page).to have_selector('li', text: mp.content) 
    end 
    end 
end 
+0

Причина, по которой вы иждивенцы не уничтожены, заключается в том, что 'delete' пропускает обратные вызовы. Другими словами, обратные вызовы, необходимые для уничтожения связанных моделей, никогда не называются. Вместо этого используйте 'destroy'. – Jesper

+0

Я вижу, хороший улов. Я помню, что читал это, но когда я написал тест, у меня был метод HTTP DELETE. Итак, теперь после (: all) это происходит, и он удаляет все связанные тестовые микропосты: 'after (: all) do @ user_with_many_posts.destroy end' – equalizer

+0

Хорошо, пост обновлен, чтобы отобразить правильные 'after (: все) '. Теперь, если у кого-то есть представление о том, почему этот тест в целом работает только тогда, когда это делается как ': each' ... – equalizer

ответ

0

Капибара сбрасывает сеанс связи между каждым примером перспективой увидеть этот ответ: https://stackoverflow.com/a/9789326/648392

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

Другими словами, вы можете настроить любые модели, необходимые в вашей спецификации в before(:all) блоке, но вы должны переместить сеанс связанные вещи, как valid_session и visit root_path к before(:each) блока.

+0

Спасибо, это имеет смысл, и это исправлено! Из моего опыта JUnit я не ожидал этого (по крайней мере, так, как он был настроен, когда я его использовал). – equalizer