我知道控制器规范中的expect(assign(:var))
测试@var
被分配给某个值。在我的情况下,我想测试此@var
是否收到特定消息。如果我在get :action
之前执行此操作,则分配返回nil。如果我之后这样做,那么期待这条消息为时已晚。
# controller
def action
@var = something
@var.message
render :nothing
end
# spec1
expect(assigns(:var)).to receive(:message) # not working, var is nil
get :action
# spec2
get :action
expect(assigns(:var)).to receive(:message) # not working, expectation too late
答案 0 :(得分:2)
你在这里看的是测试双打或嘲笑。您可以通过添加rspec-mocks gem或其他测试双宝石来使用它们,例如RR。
一旦你有其中一个(我个人使用RR),你可以这样做(RR的语法):
mock(assigns(:var)).foo
get :action
对rspec-mocks
的语法不是100%肯定,但它看起来应该是这样的:
var = double(assigns(:var))
expect(var).to receive(:foo)
get :action
如果您需要添加更多支票,则应查看Message Expectations和Expecting Arguments的自述文件。
答案 1 :(得分:0)
由于变量在控制器中以相同的方法分配和调用,我不相信你有办法在它之间捕获并模拟它。
相反,我通常期望“any_instance_of”像这样:
expect_any_instance_of(ClassOfVar).to receive(:message)
答案 2 :(得分:0)
我目前正在强制控制器实例变量以期望消息开启。虽然这有效,但它会跳过加载逻辑(cancan),所以我为此创建了另一个测试:
it "loads and authorizes object" do
get :action, id: 10
assert_response :success
end
it "calls action on object" do
controller.instance_variable_set('@var', @my_real_object_or_mock_here)
expect(@my_real_object_or_mock_here).to receive(:message)
get :action, id: 10
assert_response :success
end
我有点觉得这个解决方案很苛刻,但如果这个答案获得最多的选票,我会接受它:)