【问题标题】:Rails mock_model returning TrueClass?Rails mock_model 返回 TrueClass?
【发布时间】:2010-10-24 03:32:44
【问题描述】:

尝试在 Rspec 中测试控制器。 (Rails 2.3.8、Ruby 1.8.7、Rspec 1.3.1、Rspec-Rails 1.3.3)

我正在尝试发布创建但我收到此错误消息:

ActiveRecord::AssociationTypeMismatch in 'ProjectsController with appropriate parameters while logged in: should create project' User(#2171994580) 预期,得到 TrueClass(#2148251900)

我的测试代码如下:

def mock_user(stubs = {})
  @user = mock_model(User, stubs)
end

def mock_project(stubs = {})
  @project = mock_model(Project, stubs)
end

def mock_lifecycletype(stubs = {})
  @lifecycletype = mock_model(Lifecycletype, stubs)
end

it "should create project" do
  post :create, :project => { :name => "Mock Project", 
    :description => "Mock Description",
    :owner => @user,
    :lifecycletype => mock_lifecycletype({ :name => "Mock Lifecycle" }) }
  assigns[:project].should == mock_project({ :name => "Mock Project",
    :description => "Mock Description",
    :owner => mock_user,
    :lifecycletype => mock_lifecycletype({ :name => "Mock Lifecycle" })})
  flash[:notice].should == "Project was successfully created."
end

当我尝试在上面的代码中执行:owner => @user 时,问题就来了。出于某种原因,它认为我的@user 是TrueClass 而不是User 类对象。有趣的是,如果我注释掉post :create 代码,然后我做一个简单的@user.class.should == User,它就可以工作,这意味着@user 确实是一个User 类对象。

我也试过

:owner => mock_user
:owner => mock_user({ :name => "User",
  :email => "user@email.com",
  :password => "password",
  :password_confirmation => "password })
:owner => @current_user

注意@current_user 也被模拟为用户,我对其进行了测试(同样的方式,@current_user.class.should == User),并且当我尝试设置 :owner 时还返回一个TrueClass

有人知道为什么会这样吗?

谢谢!

【问题讨论】:

    标签: ruby-on-rails mocking rspec functional-testing


    【解决方案1】:

    据我所知,在post 语句中引用它之前,您并没有创建实例变量@user。您最好在发布之前创建实例变量,以便先决条件立即显而易见。这样你就可以知道@user是否被设置了。

    我知道有些人更喜欢单行代码更好,因为我很聪明地编写这样的东西,但我发现明确甚至重复是一个非常好的主意,尤其是在测试中。

    我正在添加以下代码,我相信这些代码可以更好地表达您的意图。在我的代码中,我使用模拟期望来“期望”Project 是使用一组特定的参数创建的。我相信您的代码假定您可以在新创建的模拟项目和在控制器执行期间创建的不同项目之间进行相等比较。这可能不是真的,因为它们是截然不同的对象。

    在我的代码中,如果您对 TrueClass 等的评估有疑问,您可以在示例中使用像 user.should be_a(User) 这样的代码行来确保正确连接。

    def mock_user(stubs = {})
      mock_model(User, stubs)
    end
    
    def mock_project(stubs = {})
      mock_model(Project, stubs)
    end
    
    def mock_lifecycletype(stubs = {})
      mock_model(Lifecycletype, stubs)
    end
    
    it "should create project" do
      user = mock_user
      owner = user
      lifecycletype = mock_lifecycletype({ :name => "Mock Lifecycle" })
    
      # Not certain what your params to create are, but the argument to with
      # is what the params are expected to be
      Project.should_receive(:create).once.with({:user => user, :owner => owner, :lifecycletype => lifecycletype})
    
      post :create, :project => { :name => "Mock Project", 
        :description => "Mock Description",
        :owner => @user,
        :lifecycletype => lifecycletype }
      flash[:notice].should == "Project was successfully created."
    end
    

    【讨论】:

    • 附带说明,设定期望可能比测试平等更有效。测试相等性会引发“== 在这种情况下意味着什么?”的问题。
    • 啊,很抱歉!我正在创建用户。我有一个 before(:each) 块来设置我需要的一切。另外,我发现了问题。在我的控制器中,我有一行设置:@project.owner = current_user....如果我将其更改为@project.owner_id = current_user.id,一切正常。奇怪。
    猜你喜欢
    • 2014-04-26
    • 2011-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-17
    • 2019-05-20
    • 1970-01-01
    相关资源
    最近更新 更多