如何验证在Rails中创建了记录



我有一个小型Rails应用程序,该应用程序的数据库包含不同的Languages。这些Languages中的每一个都会发生变化,我想跟踪它们的变化
我通过在对象更改时创建一个Audit记录来完成此操作。该Audit具有验证关系的has_many :languages, through: :audit_language_couplings字段。

class Audit < ApplicationRecord
belongs_to :audit_type
has_many :audit_language_couplings
has_many :languages, through: :audit_language_couplings
validates_presence_of :audit_type, :admin_id, :date, :before
end
class Language < ApplicationRecord
has_many :audit_language_couplings
has_many :audits, through: :audit_language_couplings
validates_presence_of :iso_code, :display_name, :keyboard_layout, :flag_url, :luis_app_identification, :luis_authorized_key, :luis_location
end

当调用PUTDELETEPOST方法时,通过调用LanguagesController中的create_audit()方法来创建审核。我还有一个/languages/:id/audits端点,它以JSON形式返回给定语言的所有审计。

create_token()方法:

def create_audit(type, admin_id)
@language.audits.create(
audit_type_id: type,
admin_id: admin_id,
date: Time.now.to_date,
before: @language.to_s # TODO: Use the to-be-created to_json() or to_s() method instead.
)
end

这也是我问题的本质(我认为(。我目前正在用RSpec和工厂机器人程序请求测试我的API。当我在测试中创建或更新Language时,由于某种原因,没有创建Audits。但我知道代码是有效的,因为当我在我的开发环境中使用poster手动执行时,它是有效的。

FactoryBot.define do
factory :language do
iso_code { Faker::Address.country_code }
display_name { Faker::Address.country }
keyboard_layout { Faker::Internet.url }
flag_url { Faker::Internet.url }
luis_app_identification { Faker::Lorem.characters(5) }
luis_authorized_key { Faker::Lorem.characters(5) }
luis_location { Faker::Lorem.characters(5) }
end
end

我目前的测试结构如下:

describe 'POST /admin/language' do
let(:valid_attributes) do
{
payload: {
iso_code: 'en-US',
display_name: 'English (US)',
keyboard_layout: 'QWERTY',
flag_url: '/public/images/en-US.png',
luis_app_identification: 'test',
luis_authorized_key: 'test',
luis_location: 'test'
}
}
end
context 'when the request is valid' do
before { post '/admin/languages', params: valid_attributes, headers: token_header }
it 'creates a language' do
expect(json['iso_code']).to eq('en-US')
end
it 'returns status code 201' do
expect(response).to have_http_status(201)
end
context 'an audit should be made for the change' do
before { get "/admin/languages/#{language_id}/audits", headers: token_header }
it 'creates 1 audit' do
expect(json.size).to eq 1
end
it 'is an audit of type 1 [ADD]' do
expect(json[0]['audit_type_id']).to eq 1
end
end
end
context 'when the request is invalid' do
before do
post '/admin/languages', headers: token_header, params:
{
payload: {
display_name: 'English (US)',
keyboard_layout: 'QWERTY',
flag_url: '/public/images/en-US.png',
luis_app_identification: 'test',
luis_authorized_key: 'test',
luis_location: 'test'
}
}
end
it 'returns status code 422' do
expect(response).to have_http_status(422)
end
it 'returns a validation failure message' do
expect(response.body).to match(/Validation failed: Iso code can't be blank/)
end
end
end

我检查审计的测试失败了,因为使用RSpec运行代码时返回0个审计。

我想我在工厂里做错事,但我不确定,请告诉我!

干杯

根据提供的代码很难说到底发生了什么,但您可以尝试将create_audit方法更改为:

def create_audit(type, admin_id)
@language.audits.create!(

如果由于某种原因创建失败,将!(bang(添加到create方法将引发异常,该异常应显示在RSpec日志中。这至少可以帮助你找到问题的根源。

您需要检查的是,当发布时,Audit实例的数量增加了一个。我会这样做:

subject { post '/admin/languages', params: valid_attributes, headers: token_header }
it 'creates an audit'
expect { subject }.to change { Audit.count }.by(1)
end

目前,您测试是否有一个审计(不检查规范之前有多少(,并通过间接方法(在第一个审计之后调用另一个API端点(。

Pennycracker和ReggieB的答案都是正确的,或者实际上是大局的一部分。

关于CCD_ 19舍邦的部分将我引向实际问题。工厂没有创建Audit所依赖的AuditType
ReggieB认为我的测试设置有缺陷,因为我正在测试一个嵌套的请求。

我选择使用他的建议的修改版本,一个更适合我当前设置的版本:

context 'when the request is valid' do
before { post '/admin/languages', params: valid_attributes, headers: token_header(admin_id: admin.id) }
it 'returns status code 201' do
expect(response).to have_http_status(201)
end
context 'the audit system has to be updated' do
it 'creates 1 audit' do
expect(Audit.all.size).to eq(1)
end
it 'should have type 1 [ADD]' do
expect(Audit.first.audit_type.id).to eq(1)
end
end
end

数据库清理器gem在每个示例之后都会清理数据库,因此检查第一个Audit的工作原理与预期更改的工作原理相同。

感谢大家的帮助。

相关内容

  • 没有找到相关文章

最新更新