ruby 序列化程序测试的RSpec相等匹配器失败

y1aodyip  于 2023-08-04  发布在  Ruby
关注(0)|答案(4)|浏览(125)

我正在为我的一个活动模型序列化器编写一个测试,以确保JSON输出是我所期望的。然而,我不明白为什么RSpec解析我的'expected'输出而忽略了我的testjob数组,我不明白为什么我不能让'expected'和'got'输出彼此相等。有一次,我甚至将'got'结果复制粘贴到我的'expected'输入,仍然收到一条失败消息,表明两个字符串不相等。然而,当我在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

gpfsuwkq

gpfsuwkq1#

您的testjobs似乎不匹配

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

字符串
vs

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


您应该设置您的规格,以便也返回testjobs
请注意,中间的diff字符串是cut--这是eq matcher与字符串一起使用时最烦人的部分之一。
编辑:你可能习惯于切换到比较数组/哈希而不是字符串来获得更好的差异。expect(serializer).to eq {testrun: "..."}(在Assert中删除to_json

drnojrws

drnojrws2#

这不会回答你的问题,但会让你回答你的问题。将其添加到spec_helper.rb,结果将不再被中心截断,因此中间没有神秘的块丢失。

config.expect_with :rspec do |expectations|
    expectations.max_formatted_output_length = nil
  end

字符串
如果你不想看到兆字节长的消息,你也可以使用像10005000这样的int来代替nil(无限长度)。

62o28rlo

62o28rlo3#

您的测试没有通过的原因是微不足道的:在it块中,您在创建Testjob记录时分配了Testrun id (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

改进范围:

请查看active_model_serializers存储库中的:json适配器测试:https://github.com/rails-api/active_model_serializers/blob/v0.10.6/test/action_controller/json/include_test.rb的数据。
您可以使用rspec轻松地将测试转换为套件。
如果你想测试json输出,那么你应该把测试放在controllerrequest规范下;而不是在序列化器中。因为呈现JSON是适配器的责任;序列化程序只向适配器提供其中定义的所有属性和关联。

zqry0prt

zqry0prt4#

工作溶液:我添加了serializer.testjobs << testjob行来显式地将testjob与对象关联起来,现在测试通过了。

相关问题