2010-09-15 1 views
0

Вот мой код, я spec'ing:Научиться spec..seem, возникли проблемы

def vote_up 
    get_vote 
    @vote.value += 1 unless @vote.value == 1 
    @vote.save 
    respond_to do |format| 
    format.js { render :action => "vote", :layout => false } 
    end 
end 

Кажется довольно просто. Это то, что я пытаюсь чертежу его:

it "should vote up" do 
    @mock_cat = Factory.create(:category) 
    Category.stub(:mock_cat) 
    @mock_post = Factory.create(:post) 
    Post.stub(:current_post).and_return(@mock_post) 

    @vote = Factory(:vote) 

    get :vote_up, :id => @vote 
    @vote.reload.value.should == 1  
    end 

Это возвращение этого:

undefined method `to_i' for #<Vote:0x1052a4af8> 

Я не могу понять, почему же. Если бы я запустил свой mock_vote как (: vote), не пропустил бы он через метод контроллера и не прислал бы +1 к нему?

Update

Вот частный метод из моего posts_controller.rb

private 

def get_vote 
    current_post = Post.all.detect{|r| r.id == params[:id].to_i} 
    @post = current_post 
    @vote = current_post.votes.find_by_user_id(current_user.id) 
    unless @vote 
    @vote = Vote.create(:user_id => current_user.id, :value => 0) 
    current_post.votes << @vote 
    end 
end 

Ответ:

it "should vote up" do 
    @mock_cat = Factory.create(:category) 
    Category.stub(:mock_cat) 
    @post = Factory(:post) 

    get :vote_up, :id => @post.id 
    @post.reload.vote_score.should == 1  
    end 
+1

Почему в мире вы делаете 'Post.all.detect' вместо of 'Post.find (params [: id])'? –

+0

Также 'Category.stub (: mock_cat)' не делает то, что вы хотите. Фактически это создание метода класса в 'Category' под названием' mock_cat', который, очевидно, никогда не вызван. –

+0

Я не могу обвинить ночь питья за метод Post.all.detect. Абсолютно верно, используя последнее. Во-вторых, мне нужно что-то создать, потому что пост не может существовать без категории. Поэтому я блокирую один, чтобы сделать содержание моделей. – Trip

ответ

1

Это трудно следовать, что именно ваши окурки делаете, потому что вы не размещал код для get_vote. Но я думаю, что вы переусердствовали с заглушками, когда могли просто воспользоваться теми фабриками, которые вы уже создали.

it "should vote up" do 
    # Does your Vote belong to a post or a category or anything? I don't know. 
    # Modify as needed -- Factory(:vote, :post => Factory(:post)) 
    @vote = Factory(:vote) 

    get :vote_up, :id => @vote 
    @vote.reload.value.should == 1 
end 

Примечание reload. Ваш контроллер изменяет запись, которую мы уже вытащили из базы данных, поэтому нам нужно перезагрузить ее, чтобы проверить ее новое значение.

+0

Отличный пункт. Я думаю, что я должен ввести 12-ступенчатую программу-заглушку для моей зависимости :). Я попробовал свой код с моим и разместил его выше, и он вернул 'undefined метод' to_i 'для # 'error. Наверное, как и вы сказали, из-за моего метода get_vote. – Trip

+0

Я собирался обновить свой ответ, как это сделать, но мне кажется, что я попадаю на территорию, где я просто пишу ваше приложение для вас.Отладка этой ошибки довольно проста - где вы вызываете 'to_i'? В блоке 'Post.all.detect'. Почему это не удается? В вашей спецификации вы передали ': id => @ vote', где @vote - объект Vote ** **, который не имеет метода' to_i'. Поэтому измените его на ': id => @ vote.id' или просто используйте' Post.find (params [: id]) ', который автоматически вызывает' to_param', который по умолчанию является атрибутом 'id' объекта. –

+0

ах, ты по-настоящему мудр. Вы научили человека ловить рыбу, правда. Я только что закончил его и обновил свой ответ выше. – Trip

2

Я рекомендую перемещать логику от контроллера к модели. Модели намного проще в спецификации. Вместо того, чтобы:

def vote_up 
    get_vote 
    @vote.value += 1 unless @vote.value == 1 
    @vote.save 
    respond_to do |format| 
    format.js { render :action => "vote", :layout => false } 
    end 
end 

Ваш контроллер должен выглядеть следующим образом:

def vote_up 
    @vote = Vote.vote_up(params[:id]) 
    respond_to do |format| 
    format.js { render :action => "vote", :layout => false } 
    end 
end 

или, если вам действительно нужно get_vote (может быть, вы должны переместить его в before_filter?)

def vote_up 
    @vote.vote_up 
    respond_to do |format| 
    format.js { render :action => "vote", :layout => false } 
    end 
end 

Если необходимо. добавить исключения (может быть с rescue_from)

Затем вам нужно спецификации только в модели, и некоторая интеграция (rspec, steac, огурец)

+0

Отличная рекомендация. Никогда не думал об этом раньше. – Trip