我一直非常喜欢使用contexts
,subjects
和its
和rspec来真正清理我的测试代码。典型例子:
context "as a user" do
subject{ Factory :user }
its(:name){ should == "Bob" }
end
我无法弄清楚的是我如何使这个条件动态(即基于其他对象)。 its
似乎实例化了该块中的属性,因此我无法访问它周围的所有内容。我喜欢做类似的事情:
its(:name){ should == subject.contact.name }
但我看不出任何实现这一目标的方法。有没有人知道是否有一个方法代理到这个实例eval,它提供了对原始对象的访问?或者,如果有任何其他方式,我可以使用我正在检查的属性实例范围之外的方法?
似乎subject
块中的its
变为实际属性(在这种情况下为name
)
有趣的是,我可以访问我的任何let
方法,但同样,我无法访问我的原始subject
有问题。
您几乎在回答自己,在设置主题之前使用let
分配。然后你可以随处参考:
context "as a user" do
let(:user) { Factory(:user) }
subject { user }
its(:name) { should == user.contact.name }
end
我也是context
,subject
,its
爱好者!
不确定是否有办法完全按照你的要求去做,因为块内的“主题”成为User#name
的返回值。
相反,我使用let
方法以及以下规范样式来编写这种测试:
describe User do
describe '#name' do
let(:contact) { Factory(:contact, name: 'Bob') }
let(:user) { Factory(:user, contact: contact) }
subject { user.name }
it { should == 'Bob' }
end
end
这当然会对您的联系人所代表的内容做出一些假设(这里是一个关联或类似的)。您也可以选择存储User#contact
的返回值,而不是依靠FactoryGirl来建立“真实”关联。
无论您在这些方面做出何种选择,这一策略对我来说都很有效。我发现它允许我更简洁地了解正在测试的内容,同时保留关于预期返回值来自何处的信息(针对其他开发者和未来的自我)。
您可以在主题块中设置实例变量:
context 'as a user' do
subject { @user = FactoryGirl.create(:user) }
its(:name) { should == @user.name }
end