ruby Rails:使用RSpec测试命名范围

lokaqttq  于 2023-08-04  发布在  Ruby
关注(0)|答案(5)|浏览(113)

我是测试Rails Web应用程序和RSpec的新手。我使用遗留代码,需要添加测试。那么,用RSpec测试查找器和命名作用域的最佳方法是什么呢?
我在Google上找到了一些方法,但它们并不理想。举例来说:
http://paulsturgess.co.uk/articles/show/93-using-rspec-to-test-a-named_scope-in-ruby-on-rails

it "excludes users that are not active" do
    @user = Factory(:user, :active => false)
    User.active.should_not include(@user)
end

字符串
或者是
http://h1labs.com/notebook/2008/8/21/testing-named-scope-with-rspec

it "should have a published named scope that returns ..." do
  Post.published.proxy_options.should == {:conditions => {:published => true}}
end


我在“铁路测试处方”中找到了最佳方法(恕我直言):

should_match_find_method :active_only { :active == true }


其中should_match_find_method自定义辅助方法

0tdrvxhp

0tdrvxhp1#

RSpec的创建者最近在博客上说他认为Validations are behavior, associations are structure。换句话说,他发现关联(和范围)不应该被直接测试。这些测试将根据您想要的行为进行。
换句话说,目前的观点是不需要直接测试每个作用域,因为您将通过测试应用程序的行为来覆盖这些关联。

yjghlzjz

yjghlzjz2#

大卫Chelimsky测试范围(更新)

大卫Chelimsky的例子,(由Sam Peacey的评论链接),现代化。

# app/models/user.rb

class User < ActiveRecord::Base
  scope :admins, -> { where(admin: true) }
end

个字符
这会产生一个更像“规范”的输出(当使用--format文档时):

User
  .admins
    includes users with admin flag
    excludes users without admin flag


关于这个答案的起源:
当时RSpec的负责人大卫Chelimsky回答了这个问题,Sam Peacey的链接比实际答案获得了更多的选票。答案是不容易找到和遵循,因为他是回复某人和编辑他们的答案在一个电子邮件链。这个答案清理了这个问题,并更新了RSpec代码,我猜,他今天会写它。

lb3vh1jj

lb3vh1jj3#

https://coderwall.com/p/hc8ofa/testing-rails-model-default_scope-with-rspec

  • 无数据库查询
  • 不需要在结构中表示查询

示例如下:

class Trip < ActiveRecord::Base
  default_scope { order(departure: :asc) }
  ...
end

RSpec.describe Trip, type: :model do
  it "applies a default scope to collections by departure ascending" do
    expect(Trip.all.to_sql).to eq Trip.all.order(departure: :asc).to_sql
  end
end

字符串

9q78igpj

9q78igpj4#

除非必要,否则不要使用指定的内窥镜。一个可以测试命名的范围与0调用数据库。但是我们必须停止使用名称范围,只使用类方法。这样就可以轻松测试您的应用程序,而无需测试不相关的API。这里有一个我喜欢在代码库中看到的例子,看看这个代码。它Assert#是用期望的参数调用的。我们不需要更深入地测试ActiveRecord ORM或使用昂贵的东西,如创建记录,然后将它们作为查询的结果。

describe ".with_expired_membership" do
      before do
        allow(described_class).to receive(:where)
      end

      it "returns the expired membership views" do
        described_class.with_expired_membership
        expect(described_class).to have_received(:where).with(
          "(DATE(certified_at) < ? OR date(certified_at) IS NULL)",
          1.year.ago.to_date,
        )
      end
    end

字符串
不使用名称作用域的原因在于存根对象的复杂性以及避免与数据库交互的where链。

nhaq1z21

nhaq1z215#

第一种方法的问题是它实际上是查询数据库。这是缓慢和不必要的。如果你不介意,你可以安全地使用第一种方法。第二种方法是快速和清晰的,所以我会推荐它。

相关问题