我试图在不使用灯具的情况下为控制器编写规格(而是使用模拟模型)。该控制器要求用户登录,我正在使用 AuthLogic 作者的建议

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)

我不知道如何解决这个问题;用嘲笑:改变了吗? =>假合适吗?

有帮助吗?

解决方案

Iain发布了使用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。我讨厌回答我自己的问题,但这是我正在寻找的答案;我只是没有及早发现它。

其他提示

Authlogic希望记录的行为类似于活动记录实例。您可以使用实例或模拟,但如果使用模拟/存根,则必须确保它响应Authlogic所需的所有方法。

我建议使用真正的活动记录对象而不是模拟。如果您不想使用灯具,可以使用工厂。

最后一个选项是传递一个响应任何方法的模拟(您可以通过method_missing轻松完成此操作)。该解决方案的问题在于您事先不知道哪个值应该返回任何特定的方法调用。

是的,你可以传递假,但这不是一个真正的解决方案。它需要手动尝试/添加默认值,直到您发现模拟对象回答所有Authlogic请求。但这需要您不断跟踪authlogic以进行任何内部更改,以修复对您存根的未应答呼叫。

在Rails 3中,这种对UserSession的模拟不再起作用,因为AuthLogic的UserSession不是ActiveRecord :: Base的实例。修复对我有用:

class UserSession < Authlogic::Session::Base
  extend ActiveModel::Naming
end

我发现嘲弄authlogic对象很难,我最终放弃了嘲笑。相反,我现在使用 object daddy 的发电机方法。我的功能测试现在更快乐了。顺便说一下, shoulda + object_daddy绝对撼动。 Shoulda的事务上下文确保我的测试数据库保持干净,并且我不必首先模拟简单的activerecord对象。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top