我有三个模特:
UserCompanyCommitmentCommitment是Users和Companies的HABTM连接表(也就是说,当User加入Company时,它会创建一个新的Commitment)。它还有几个额外的列/属性:
admin (用户是否拥有该公司的管理权限?)confirmed_by_admin (公司管理员是否确认了该用户加入该公司的请求?)confirmed_by_member (用户本人是否已经确认了加入该公司的邀请?)我还定义了一种方便的方法,可以快速确定是否完全确认了承诺:
class Commitment < ApplicationRecord
def confirmed?
confirmed_by_admin? && confirmed_by_member?
end
end现在我正在编写一个请求规范,但出于某种原因,change匹配器只处理它的两个语法中的一个:
let :carol { FactoryGirl.create(:user) }
let :company { FactoryGirl.create(:company) }
it 'confirms invitation to join company' do
# Initialize unconfirmed commitment
FactoryGirl.create(:commitment, user: carol,
company: company,
confirmed_by_admin: true)
expect do
patch commitment_path(carol.commitments.first),
params: { commitment: { confirmed_by_member: true } }
# for the following syntaxes, ------------------------------------------------
# this works:
end.to change { carol.commitments.first.confirmed?) }.from(false).to(true)
# and this fails:
end.to change(carol.commitments.first, :confirmed?).from(false).to(true)
# ----------------------------------------------------------------------------
end在对更改进行carol.commitments.first测试时,RSpec似乎没有被重新加载--我得到了以下测试输出:
Failure/Error:
expect do
patch commitment_path(carol.commitments.first),
params: { commitment: { confirmed_by_member: true } }
end.to change(Commitment.find_by(user: carol, company: company), :confirmed?).from(false).to(true)
expected #confirmed? to have changed from false to true, but did not change
# ./spec/requests/commitments_spec.rb:69:in `block (3 levels) in <top (required)>'怎么回事?显然,我可以坚持使用卷曲大括号/块语法,但我想了解为什么其中一种能工作,而另一种则不行。
发布于 2017-07-24 09:36:55
在检查文档并试用一个复制您的场景的新rails项目时,我相信失败的原因是
.change的“块”形式被运行了两次(“在”之前“”和“在”expect块之后),不管该块的内部是什么:
.change{ carol.commitments.first.confirmed? }.change的“方法”形式是为第一个参数运行一次:carol.commitments.first,而对于第二个参数:confirmed?运行两次。但是,这方面的问题是,规范文件中此时的carol.commitments.first与实际在commitments_controller#update中更新的对象没有共享相同的内存空间(很可能该对象名为@commitment)。尽管它们是相同的Commitment记录,但它们是单独的实例,而另一个实例的属性值在另一个实例更改时不会自动更改。请考虑下面的示例,其中演示了此“方法”表单工作的场景:
it 'sometest' do
commitment = FactoryGirl.create(:commitment, user: carol,
company: company,
confirmed_by_admin: true)
expect do
# this commitment object is exactly the same object passed in the `change` below
commitment.confirmed_by_member = true
end.to change(commitment, :confirmed?).from(false).to(true)
end免责声明:这是未经验证的,但因为它太复杂,我写评论(所有的样本测试代码),我写在这里作为一个答案。如果有谁知道得更好,请告诉我。
https://stackoverflow.com/questions/45274875
复制相似问题