Ruby on rails 序列化程序测试的RSpec相等匹配程序失败

Ruby on rails 序列化程序测试的RSpec相等匹配程序失败,ruby-on-rails,json,ruby,rspec,active-model-serializers,Ruby On Rails,Json,Ruby,Rspec,Active Model Serializers,我正在为我的一个活动模型序列化程序编写测试,以确保JSON输出符合我的预期。然而,我不明白为什么RSpec解析我的“预期”输出而忽略了我的测试作业数组,我也不明白为什么我不能让“预期”和“得到”输出彼此相等。有一次,我甚至将“get”结果复制粘贴到我的“预期”输入中,但仍然收到一条失败消息,表明两个字符串不相等。但是,当我在REPL中使用=比较这两个字符串时,输出为true。如何解决这些问题以获得有效的测试 RSpec Error: Failures: 1) TestrunSeriali

我正在为我的一个活动模型序列化程序编写测试,以确保JSON输出符合我的预期。然而,我不明白为什么RSpec解析我的“预期”输出而忽略了我的测试作业数组,我也不明白为什么我不能让“预期”和“得到”输出彼此相等。有一次,我甚至将“get”结果复制粘贴到我的“预期”输入中,但仍然收到一条失败消息,表明两个字符串不相等。但是,当我在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
以下是实际的序列化程序:

class TestrunSerializer < ActiveModel::Serializer
  attributes :id, :run_at, :started_at, :state, :completed_at, :testjobs
  has_many :testjobs
  has_one :branch
end 
类TestrunSerializer
使用的技术:Rails 5.1、RSpec 3.6、Ruby 2.4

看起来您的
测试作业不匹配

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

您应该设置您的规格,以便
测试作业
也被返回

请注意,中间的DIFF字符串为代码>剪切< /代码>,这是使用字符串时EQ匹配器中最烦人的部分。

编辑:您可能不习惯切换到比较数组/哈希而不是字符串来获得更好的差异
expect(序列化程序)。要均衡{testrun:“…”}
(将
放到断言中的json

工作解决方案: 我加了一行
serializer.testjobs您的测试没有通过的原因很简单:在
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

改善范围: 请查看
活动\u模型\u序列化程序中的
:json
适配器测试

您可以轻松地将测试转换为带有
rspec
的套件


如果您想测试json输出,那么应该将测试放在
controller
request
规范下;而不是在序列化程序中。因为呈现json是适配器的责任;序列化程序仅向适配器提供其中定义的所有属性和关联。

字符串不相等。我看不出确切的原因,因为它们被截断了。但是仍然可以看到一个差异:
“在\”完成的\“:nu…r \”
“在\”完成的\“:nu…s\”:[]
——我建议您找出实际的差异是什么!我注意到了。这几乎就像RSpec在我放置
testjobs:[]
的地方自动截断字符串一样。为什么会这样?我怀疑这可能与为什么字符串会扭曲有关,但我不明白RSpec是如何或为什么这样做的。这只是长字符串的问题。切换到比较散列/数组以获得更好的差异(检查我的更新答案)对不起。这种猴子式的修补应该避免。请看一下我的答案,以便详细说明:
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