4

我正在尝试在不使用固定装置(而不是使用模拟模型)的情况下为控制器编写规范。这个控制器需要一个用户登录,我正在使用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)

我不确定如何解决这个问题;嘲讽:changed? => false恰当吗?

4

4 回答 4

6

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

我已将此纳入我的规格,我发现它完全符合我的期望。我有为登录用户开发模拟模型的工作控制器规范,所以现在当我向用户添加字段时它们不会全部中断。Iain 在规范中实现这一点的示例如下:

describe SecretsController do
  before { login }
  it "should be very very secret!"
end

PS我讨厌回答我自己的问题,但这是我一直在寻找的答案;只是我发现的还不够早。

于 2009-06-23T15:10:32.700 回答
1

Authlogic 期望记录像一个活动记录实例一样工作。您可以使用真实实例或模拟,但如果您使用模拟/存根,则必须确保它响应 Authlogic 所需的所有方法。

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

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

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

于 2009-06-22T07:06:19.207 回答
1

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

class UserSession < Authlogic::Session::Base
  extend ActiveModel::Naming
end
于 2011-03-25T15:51:49.143 回答
0

我发现模拟 authlogic 对象很难,我最终放弃了模拟。相反,我现在使用使用对象 daddy的生成器方法。我的功能测试现在快乐多了。顺便说一句,应该+object_daddy 绝对摇滚。Shoulda 的事务上下文确保我的测试数据库保持干净,并且我不必首先模拟简单的活动记录对象。

于 2009-06-22T10:43:49.407 回答