我有一个RSpec控制器规格,简直不会通过。我正在尝试测试一个类似按钮,这是一个AJAX帖子请求,用于更新帖子下显示页面上的喜欢数量。当我在localhost上进行物理测试时,我可以按照预期点击帖子下方的“喜欢”按钮,并将喜欢的数量增加1。当我运行我的控制器规范时,它始终失败:
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}.by(1)
的一些变体,包括但不限于:expect { post1.votes }.to change{post1.votes}.from(1).to(2)
,但它仍未通过。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
。我不知道我在哪里出错了。我还制作了一个类似的功能规范:
/spec/features/liking_spec.rb
"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();
}
});
});
});
这也会失败并显示与上述相同的消息。
这是我的AJAX请求,点击&#34;喜欢&#34;和喜欢的数量增加1。
应用程序/资产/ Javascript角/ like.js
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
在我的帖子控制器中:
应用程序/控制器/ posts_controller.rb
<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>
最后,这是我的show.html.erb,其中like按钮是。
{{1}}
如果您需要其他信息,请与我们联系。
答案 0 :(得分:2)
您未正确使用expect {}.to change ...
。
它应该是expect { the action that causes the change }.to change { the value that will change }.by(1)
在您的控制器规范示例中,类似于
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 { click_button "Like"}.to change...
),您的测试很可能仍会失败,因为当click_button "Like"
返回时实际上未更新投票计数。这是因为click_button
异步触发行为然后返回。你真的不应该在功能测试中测试数据库值的更新,而应该检查页面上的可见值是否有变化,但是如果你坚持在那里检查数据库值,你将需要使用某种类型的等待匹配器(https://github.com/abotalov/waiting_rspec_matchers)或点击按钮后休眠。