如何在 Rspec 中使用 ActiveModel::Lint::Tests

How to use ActiveModel::Lint::Tests in Rspec

对于默认 Rails,您可以添加所谓的 ActiveModel::Lint::Tests 以查看您的模型是否遵守 ActiveModel 的部分内容。

我想在我的 Rspec 测试中调用这些,或类似的名称。

是否有技巧可以 运行 并在 rspec 示例中包含 Rails 核心 ActiveModel::Lint::Tests?是否有专门为 Rspec 构建的 运行 此类 lint 测试的替代方案?

一些背景:

我正在构建不继承自 Activerecord::Base 的模型,而是充当工厂或状态机。在 Rails 中也称为服务对象。对于用户来说,这些应该感觉像 ActiveModels。像

这样的东西
@services << CompositeService.new(name: 'foo', children: [{ name: 'bar' }])
render @services

应该可以。这样的 CompositeService 应该有 activemodel 命名、部分路径、缓存 ID 等等。

我正在编写一个 gem,它提供 ActiveModel 兼容模型并使用 RSpec 3.x。

为了获得 lint 测试,我添加了 activemodel 作为开发依赖项。这也带来了 ActiveSupportMinitest。我想我可以使用类似 this gist as I have in the past, but ran into an issue 的东西来尝试让测试使用 Minitestassert.

我最后把它放在一起(归功于要点的作者)并将其放入 spec/support:

require 'active_model/lint'
require 'minitest'

RSpec.shared_examples_for ActiveModel do
  include ActiveModel::Lint::Tests
  include Minitest::Assertions

  alias_method :model, :subject

  attr_accessor :assertions

  before(:each) { self.assertions = 0 }

  ActiveModel::Lint::Tests.public_instance_methods.map(&:to_s).grep(/^test/).each do |m|
    it(m.sub 'test_', 'responds to ') { send m }
  end
end

到目前为止这似乎有效,我收到如下错误消息:

Failure/Error: it(m.sub 'test_', 'responds to ') { send m }
Minitest::Assertion:
 The model should respond to to_key

这并不理想,但目前我觉得还可以。 lint 测试非常简单 从头开始实现一个共享的例子会很简单 (参见 the source),但这样我就可以依靠 gem 来保持测试最新。