2017-02-08 5 views
0

私はRSpecコントローラ仕様を持っています。私はAJAXの投稿要求であるようなボタンをテストしようとしています。投稿の下にあるショーページの好きな数を更新します。ローカルホスト上で物理的にテストすると、ポストの下にあるlikeボタンをクリックして、好き嫌いの数を1つ増やすことができます。私は私のコントローラの仕様を実行すると、それはで失敗し続ける:RSpec Ajaxテストが合格でない場合

PostsController POST #vote a user can vote on a post increments the number of votes 

Failure/Error: expect { post1.votes }.to change{post1.votes}.by(1) 
      expected result to have changed by 1, but was changed by 0 
     # ./spec/controllers/posts_controller_spec.rb:17:in `block (4 levels) in <top (required)>' 

上記の本から来ている:私はいくつかを試してみた

/spec/controllers/posts_controller_spec.rb

require 'rails_helper' 
require 'capybara/rails' 

RSpec.describe PostsController, :type => :controller do 

    describe "POST #vote" do 

    let(:post1) {Post.create!(content: "The Content created", votes: 1, story: "My story", author: "Authors Name")} 

    context "a user can vote on a post" do 
     it "increments the number of votes" do 

     post :vote, post1: { votes: post1.votes }, 
      params: { id: post1.id }, 
      xhr: true 

     expect { post1.votes }.to change{post1.votes}.by(1) 

     end 
    end 
    end 
end 

のバリエーションには、expect { post1.votes }.to change{post1.votes}.from(1).to(2)が含まれますが、これに限定されるものではありません。私はこれでどこが間違っているのか分かりません。

/spec/features/liking_spec.rb

require 'rails_helper' 

RSpec.feature "Like feature" do 

    let!(:post) {Post.create!(content: "The Content created", votes: 1, story: "My story", author: "Authors Name")} 

    scenario "users can like quotes" do 
    visit root_path 

    click_link "Motivation" 
    click_link post.author 

    expect(page).to have_button "Like" 
    expect(page).to have_current_path post_path(post.id) 

    click_button "Like" 

    expect { post.votes }.to change{post.votes}.by(1) 

    end 
end 

は、これも上記と同じメッセージで失敗します。また、私はこのような何かを行く機能の仕様を作りました。ここで

は私のポストコントローラで

"use strict"; 

$(document).ready(function(){ 

    // On click increments likes by 1. 
    $("#liking").click(function() { 
    console.log('clicked'); 
    var id = $(this).data("id"); 
    $.ajax({ 
     url: '/posts/vote', 
     type: 'POST', 
     data: { 
      id: id, 
      increment: true 
     }, 
     success: function() { 
      var like_counter = $('#likeit'); 
      var current_count = parseInt($('#likeit').html()); 
      like_counter.html(current_count + 1); 
      $("#liking").hide(); 
     } 
    }); 
    }); 
}); 

like.js/1

アプリ/資産/ JavaScriptのことで、「のような」をクリックすると同類の増分の数のための私のAJAX要求である:

アプリ/コントローラ/ posts_controller.rb

class PostsController < ApplicationController 

    def index 
    @posts = Post.all 
    end 

    def show 
    @post = Post.find(params[:id]) 
    end 

    def vote 
    @post = Post.find(params[:id]) 
    @post.update(votes: @post.votes + 1) 
    end 
end 

最後に、ここに私のshがありますow.html.erb好きなボタンはどこですか。

<center> 
    <strong>Likes:</strong> 
</center> 
<center> 
    <p id='likeit'><%= @post.votes %></p> 
</center> 
<center> 
    <button id="liking" type="submit" data-id="<%= @post.id %>">Like</button> 
</center> 

追加情報が必要な場合はお知らせください。

答えて

2

あなたは正しくexpect {}.to change ...を使用していません。

expect do 
    post :vote, post1: { votes: post1.votes }, 
    params: { id: post1.id }, 
    xhr: true 
end.to change { post1.reload.votes }.by(1) 

注POST1上reloadコールようなものになるだろう、あなたのコントローラの仕様例ではexpect { the action that causes the change }.to change { the value that will change }.by(1)

であることを意味するマッチャがの価値を再評価するとき、それはそうですオブジェクトが更新されたポストを実行した後に投票します。

2番目の問題は機能仕様です。変更マッチャー(expect { click_button "Like"}.to change...)を正しく使用するようにそれを更新したとしても、click_button "Like"が返されたときに投票数が実際には更新されていないため、テストは失敗する可能性が高いです。これは、click_buttonがビヘイビアを非同期にトリガーしてからリターンするためです。あなたは本当に機能テストでDB値の更新をテストするべきではなく、変更されたページ上の可視値をチェックする必要がありますが、DB値のチェックを主張する場合は、何らかのタイプの待機マッチャー(https://github.com/abotalov/waiting_rspec_matchers )をクリックするか、ボタンをクリックしてからスリープします。

+0

それでした!ありがとう、@トーマスウォルポール。 さて、私は当初のような機能仕様を持っていましたが、いくつかのドキュメントやその他の質問を読んだ後に、おそらくこれが最善の方法ではないことに気付きました。だから私はコントローラの仕様に切り替えました。フィーチャ仕様のDB値をテストするべきではないことに私は同意するので、フィーチャ仕様を取り除く可能性が最も高いです。 – kyle

関連する問題