使用RSpec测试嵌套资源会导致奇怪的故障

时间:2012-10-06 14:39:31

标签: ruby-on-rails ruby testing rspec

我写这个来测试我的控制器的创建操作,它使用嵌套资源。我有一个has_many :users关联的帐户模型。注册后,将创建一个具有单个用户的帐户。

  describe "POST #create", focus: true do
    let(:account) { mock_model(Account).as_null_object }

    before do
      Account.stub(:new).and_return(account)
    end

    it "creates a new account object" do
      account_attributes         = FactoryGirl.attributes_for(:account)
      user_attributes            = FactoryGirl.attributes_for(:user)
      account_attributes[:users] = user_attributes

      Account.should_receive(:new).with(account_attributes).and_return(account)
      post :create, account: account_attributes
    end
  end

这是我得到的失败输出;注意预期和得到之间的区别:它预期一个符号,当它有一个字符串。

1) AccountsController POST #create creates a new account object
     Failure/Error: Account.should_receive(:new).with(account_attributes).and_return(account)
       <Account(id: integer, title: string, subdomain: string, created_at: datetime, updated_at: datetime) (class)> received :new with unexpected arguments
         # notice that expected has symbols while the other users strings...
         expected: ({:title=>"ACME Corp", :subdomain=>"acme1", :users=>{ ... }})
              got: ({"title"=>"ACME Corp", "subdomain"=>"acme1", "users"=>{ ... }})
     # ./spec/controllers/accounts_controller_spec.rb:34:in `block (3 levels) in <top (required)>'

我不禁注意到这段代码也有点味道。我不知道我是否正确行事。我是RSpec的新手,如果你可以提供一些关于我努力的反馈,那么我就是奖励积分。

1 个答案:

答案 0 :(得分:3)

params哈希通常包含字符串而不是符号的键。虽然我们使用符号访问它们,但这是因为它是一个Hash with indifferent access,它不关心是否使用字符串或符号访问它们。

为了让您的测试通过,您可以在设置期望时使用account_attributes哈希上的stringify_keys方法。然后,当Rspec比较哈希时,两者都将被字符串键入。


现在,关于您提出的评论:实例化帐户是否真的是您对控制器的期望?如果您将断言/期望置于更具体的,外部可见的行为上,而不是放在您的对象应该使用的每个方法上,那么您的测试将不那么脆弱。

Rails控制器通常很难测试,因为有很多等效的方法可以操作ActiveRecord模型......我通常会尽量让我的控制器变得笨拙,而我们不会对它们进行单元测试,将它们的行为留给被更高级别的集成测试覆盖。