【问题标题】:Is there a better way to test this Rails controller with RSpec?有没有更好的方法来使用 RSpec 测试这个 Rails 控制器?
【发布时间】:2014-06-13 23:32:15
【问题描述】:

我有一个 Account 模型来验证其子域是唯一的。

我正在尝试学习如何使用 RSpec 测试控制器。

这是我想出的,但它与生成的 RSpec 测试完全不同,我想知道这是否是测试它的好方法,或者是否有更好的方法。

我的测试:

describe "POST create" do
    describe "with valid params" do
      it "creates a new Account" do
        original_count = Account.count
        account = FactoryGirl.build(:account, :subdomain => 'newdomain')
        post :create, {:account => account}
        account.save!
        new_count = Account.count
        expect(new_count).to eq(original_count + 1)
      end
...

编辑

我忘了指出,在我的 spec_helper 中有以下代码。由于我处理子域的方式需要它:

config.before(:each, :type => :controller) do
    @account = FactoryGirl.create(:account)
    @user = FactoryGirl.create(:user)
    @request.host = "#{@account.subdomain}.example.com"
    sign_in @user
end

【问题讨论】:

  • 我要么还没有让这些工作,要么还没有回到这个。

标签: ruby-on-rails ruby rspec factory-bot rspec-rails


【解决方案1】:

有,通过使用 Rspec 的 expect to change 和 FactoryGirl 的 attributes_for(可能需要调整,未测试):

describe "POST create" do
    describe "with valid params" do
      it "creates a new Account" do
        expect{
          post :create, { account: attributes_for(:account) }
        }.to change{Account.count}.by(1)
      end
...

在单元测试中验证您唯一的子域约束,可能使用shoulda-matchers

describe Account do
  it { should validate_uniqueness_of(:subdomain) }
end

【讨论】:

  • 我有一个模型测试来验证我的唯一约束。
  • @Catfish 然后通过验证控制器中的唯一约束,您只是在测试 subdomain 参数是否已传递给模型。
  • 那么你是说我需要或不需要我的控制器中的验证唯一性,因为我的模型中有它?我不是很关注。此外,您的测试不起作用。它会导致此错误:Failure/Error: expect { expected result to have changed by 1, but was changed by 0。另请注意,我使用规范助手中的 before(:each) 更新了我的问题,这可能导致我的测试以某种方式失败。
  • post :create, { account: attributes_for(:account, :subdomain => 'newdomain') } 也不起作用。给出同样的错误。
  • @Catfish 我的测试不能按原样使用。这是一个例子。您必须自己完成其余的腿部工作。您的Account 工厂是否返回静态subdomain?由于唯一约束,它可能会失败,因为您已经在 before(:each) 块中创建了 Account
【解决方案2】:

我会让控制器规范成为真正的单元测试,而不涉及数据库。比如:

describe AccountsController do
  describe '#create' do
    it "creates a new Account" do
      account_attrs = FactoryGirl.attributes_for :account
      expect(Account).to receive(:create!).with account_attrs
      post :create, account: account_attrs
     end
  end
end

我还有一个功能规范(或 Cucumber 场景),它对整个交互进行了集成测试,AccountsController 的帖子是其中的一部分。实际上,如果我有一个快乐路径功能规范/场景,则不需要编写上面的控制器规范,但我需要用于错误路径的控制器规范(比如尝试创建一个具有与现有子域相同的子域的 Account Account) 和其他变体,我会通过存根和模拟数据库调用来编写它们,类似于上面的规范。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-18
    • 2012-04-28
    • 2011-05-15
    • 2019-08-26
    • 1970-01-01
    • 2014-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多