如果你在某个action中对Cookie进行了设置,然后你又打算对你设置的cookie进行测试,那么你可能会遇到麻烦,不妨看看下面这段代码:
class CookiesController
def update
cookies[:name] = 'demo'
end
end
describe CookiesController
it "should update cookies[:name] to 'demo'" do
request.cookies[:name] = 'test'
put :update
request.cookies[:name].should == 'demo'
end
end
如果你运行上面的测试,将会得到一个:expected ‘demo’ got ‘test’,这是怎么回事,cookie设置失败了?实际上这是正确的,之所以产生这样的结果是因为我们对Rails的Cookie机制不了解,首先我们需要区分request.cookies和Controller中的cookies,request.cookies是用于模拟客户端发送的 cookie的,它是一个Hash对象,因此我们可以像使用hash那样使用它:
>> request.cookies[:name] = ‘test’
>> request.cookies[:name]
test
但是Controller中的cookies则不同,它是一个ActionController::CookieJar对象,这个cookies对象实际上保存了2个cookie集合:incoming cookie和outgoing cookie。incoming cookie就是客户请求中所携带的cookie(也就是request.cookies),而outgoing cookie则是在请求处理完后将被设置回客户端的cookie。
因此尽管我们使用了[]=方法来设置cookie,但因为cookies对象重载了[]与[]=方法:
[]方法返回的是incoming cookie,也就是request中携带的cookie
而[]=方法设置的却是outgoing cookie,它只对下一个请求起作用,也就是说它会被包含在下一个请求的incoming cookie中。
因此设置controller cookies,我们只能得到:
>> cookies[:name] = ‘test’
>> cookies[:name]
nil
如果你需要测试cookies是否设置成功,那么一个简单的方法,就是将controller中的cookies替换成一个hash,比如:
describe CookiesController
it "should update cookies[:name] to 'demo'" do
request.cookies[:name] = 'test'
@cookies = {}
controller.stub!(:cookies).and_return(@cookies)
put :update
@cookies[:name].should == 'demo'
end
end