我试图在不使用灯具的情况下为控制器编写规格(而是使用模拟模型)。该控制器要求用户登录,我正在AuthLogic之后使用author's recommendations。
describe UsersController do
def mock_user(stubs={})
@mock_user ||= mock_model(User, stubs)
end
context 'when logged in' do
before { activate_authlogic }
it "exposes the logged-in user as @user in response to GET (show)" do
UserSession.create(mock_user)
...
end
...
end
...
end
这些示例都在UserSession.create(...)
行失败,报告的结果为:
Mock 'User_1005' received unexpected message :changed? with (no args)
我不知道如何解决这个问题;正在嘲笑:changed? => false
合适吗?
答案 0 :(得分:6)
Iain发布了solution to using mock objects with AuthLogic。换句话说,以下帮助者进入spec_helpers.rb
:
def current_user(stubs = {})
@current_user ||= mock_model(User, stubs)
end
def user_session(stubs = {}, user_stubs = {})
@current_user_session ||= mock_model(UserSession, {:user => current_user(user_stubs)}.merge(stubs))
end
def login(session_stubs = {}, user_stubs = {})
UserSession.stub!(:find).and_return(user_session(session_stubs, user_stubs))
end
def logout
@user_session = nil
end
我已将其纳入我的规格中,我发现它完全符合我的希望。我有工作的控制器规范,为登录用户部署模拟模型,所以现在,当我向User添加一个字段时,它们并没有全部中断。 Iain在规范中实现这一点的例子是:
describe SecretsController do
before { login }
it "should be very very secret!"
end
P.S。我讨厌回答我自己的问题,但这是我正在寻找的答案;我只是没有及早发现它。
答案 1 :(得分:1)
Authlogic希望记录的行为类似于活动记录实例。您可以使用实例或模拟,但如果使用模拟/存根,则必须确保它响应Authlogic所需的所有方法。
我建议使用真正的活动记录对象而不是模拟。如果您不想使用灯具,可以使用工厂。
最后一个选项是传递一个响应任何方法的模拟(您可以通过method_missing轻松完成此操作)。该解决方案的问题在于您事先不知道哪个值应该返回任何特定的方法调用。
是的,你可以传递假,但这不是一个真正的解决方案。它需要手动尝试/添加默认值,直到您发现模拟对象回答所有Authlogic请求。但这需要您不断跟踪authlogic以进行任何内部更改,以修复对您存根的未应答呼叫。
答案 2 :(得分:1)
在Rails 3中,这种对UserSession的模拟不再起作用,因为AuthLogic的UserSession不是ActiveRecord :: Base的实例。修复对我有用:
class UserSession < Authlogic::Session::Base
extend ActiveModel::Naming
end
答案 3 :(得分:0)
我发现嘲弄authlogic对象很难,我最终放弃了嘲笑。相反,我现在使用object daddy的生成器方法。我的功能测试现在更快乐了。 BTW,shoulda + object_daddy绝对是摇滚乐。 Shoulda的事务上下文确保我的测试数据库保持干净,并且我不必首先模拟简单的activerecord对象。