RSpec相等匹配器无法进行序列化器测试

时间:2017-09-15 14:20:02

标签: ruby-on-rails json ruby rspec active-model-serializers

我正在为我的一个Active Model Serializers编写测试,以确保JSON输出符合我的预期。但是,我无法弄清楚为什么RSpec正在解析我的'预期'输出以省略我的testjobs数组,而我不明白为什么我不能得到'预期'和'得到'输出相等。有一次,我甚至将“得到的”结果复制粘贴到我的“预期”输入中,但仍然收到两条字符串不相等的失败消息。但是,当我使用 == 比较REPL中的这两个字符串时,输出为 true 。如何解决这些问题以获得有效的测试?

RSpec Error:

Failures:

  1) TestrunSerializer creates special JSON for the API
     Failure/Error: expect(serializer.to_json).to eq('{"testrun":{"id":1,"run_at":null,"started_at":null,"state":"pending","completed_at":null,"testjobs":[{"id":2,"active":false,"testchunk_id":2,"testrun_id":1,"testchunk_name":"flair","testchunk":{"id":15,"name":"flair"}}],"branch":{"id":1,"name":"dev","repository":{"id":321,"url":"fakeurl.com"}}}}')

       expected: "{\"testrun\":{\"id\":1,\"run_at\":null,\"started_at\":null,\"state\":\"pending\",\"completed_at\":nu...r\"}}],\"branch\":{\"id\":1,\"name\":\"dev\",\"repository\":{\"id\":321,\"url\":\"fakeurl.com\"}}}}"
            got: "{\"testrun\":{\"id\":1,\"run_at\":null,\"started_at\":null,\"state\":\"pending\",\"completed_at\":nu...s\":[],\"branch\":{\"id\":1,\"name\":\"dev\",\"repository\":{\"id\":321,\"url\":\"fakeurl.com\"}}}}"

       (compared using ==)
     # ./spec/serializers/testrun_spec.rb:11:in `block (2 levels) in <top (required)>'

Finished in 0.79448 seconds (files took 5.63 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/serializers/testrun_spec.rb:8 # TestrunSerializer creates special JSON for the API

这是RSpec测试:

require 'rails_helper'

describe TestrunSerializer, type: :serializer do
  let(:repo)      { Repository.create(id: 321, url: "fakeurl.com") }
  let(:branch)    { Branch.create(id: 1,name: "dev", repository_id: repo.id) }
  let(:testchunk) { Testchunk.create(id: 15, name: "flair") }

  it "creates special JSON for the API" do
    serializer = TestrunSerializer.new Testrun.new("id":1, name: "name", "run_at": nil, state: "pending", branch_id: branch.id)
    testjob = Testjob.create(id: 8, active: false, testchunk_id: testchunk.id, testrun_id: 1)
    expect(serializer.to_json).to eq('{"testrun":{"id":1,"run_at":null,"started_at":null,"state":"pending","completed_at":null,"testjobs":[{"id":2,"active":false,"testchunk_id":2,"testrun_id":1,"testchunk_name":"flair","testchunk":{"id":15,"name":"flair"}}],"branch":{"id":1,"name":"dev","repository":{"id":321,"url":"fakeurl.com"}}}}')
  end
end

这是实际的序列化器:

class TestrunSerializer < ActiveModel::Serializer
  attributes :id, :run_at, :started_at, :state, :completed_at, :testjobs
  has_many :testjobs
  has_one :branch
end 

使用的技术:Rails 5.1,RSpec 3.6,Ruby 2.4

3 个答案:

答案 0 :(得分:0)

您的testjobs似乎不匹配

completed_at\":nu...r\"}}],\"branch\"

vs

completed_at\":nu...s\":[],

您应该设置规范,以便返回testjobs

请注意,diff字符串在中间是cut - 这是与字符串一起使用时eq匹配器中最烦人的部分之一。

编辑:您可能不会切换到比较数组/散列而不是字符串来获得更好的差异。 expect(serializer).to eq {testrun: "..."}(在断言中删除to_json

答案 1 :(得分:0)

您的测试未通过的原因很简单:在it块内,您在创建Testrun id (1)记录时分配了Testjob,但是{{1}记录不存在。

Testrun在您调用SomeActiveRecord.new()之前不会创建任何实际记录,或者您可以为此调用save()

SomeActiveRecord.create

所以最终解决方案可能类似于:

some_active_record = SomeActiveRecord.new(...)
some_active_record.save

# or
some_active_record = SomeActiveRecord.create(...)

改进范围:

请查看it "creates special JSON for the API" do testrun = Testrun.create(id: 1, name: "name", run_at: nil, state: "pending", branch_id: branch.id) serializer = TestrunSerializer.new(testrun) testjob = Testjob.create(id: 8, active: false, testchunk_id: testchunk.id, testrun_id: testrun.id) expect(serializer.to_json).to eq('{"testrun":{"id":1,"run_at":null,"started_at":null,"state":"pending","completed_at":null,"testjobs":[{"id":2,"active":false,"testchunk_id":2,"testrun_id":1,"testchunk_name":"flair","testchunk":{"id":15,"name":"flair"}}],"branch":{"id":1,"name":"dev","repository":{"id":321,"url":"fakeurl.com"}}}}') end repo:https://github.com/rails-api/active_model_serializers/blob/v0.10.6/test/action_controller/json/include_test.rb:json适配器的测试。

您可以使用active_model_serializers轻松将测试转换为套件。

如果要测试json输出,则应将测试置于rspeccontroller规格之下;而不是在序列化器中。因为渲染json是适配器的责任;序列化程序仅为适配器提供其中定义的所有属性和关联。

答案 2 :(得分:-1)

工作方案: 我添加了这条线 serializer.testjobs << testjob 显式地将testjob与对象相关联,现在测试通过了。