如何处理依赖对象(不确定如何表达)
how to treat dependent objects (not sure how to phrase this)
我正在学习 TDD 和 rails。我正在为一个 "logic" 问题伤害自己。先介绍一个情况。
我们有 3 个模型:Project
、Mission
、Attachment
。我是这样创建的
rails g model Mission
rails g model Project
rails g model Attachment title:string attachable:references{polymorphic}
rake db:migrate
什么产生了这个schema.rb
ActiveRecord::Schema.define(version: 20180307200338) do
create_table "attachments", force: :cascade do |t|
t.string "attachable_type"
t.integer "attachable_id"
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["attachable_type", "attachable_id"], name: "index_attachments_on_attachable_type_and_attachable_id"
end
create_table "missions", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "projects", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
对于模型,我们有:
# app/models/mission.rb
class Mission < ApplicationRecord
has_many :attachments, :as => :attachable
end
# app/models/project.rb
class Project < ApplicationRecord
has_many :attachments, :as => :attachable
end
# app/models/attachment.rb
class Attachment < ApplicationRecord
belongs_to :attachable, polymorphic: true
end
现在我们有了上下文,我想介绍一下我的"logic"问题。对我来说,创建一个 Attachment
是完全符合逻辑的:
Mission.find(1).attachments.create(file: 'my-file.jpg')
Project.find(1).attachments.create(file: 'my-file.jpg')
但很难想象自己会创建这样的附件:
Attachment.create(attachable: Mission.find(1))
Attachment.create(attachable: Project.find(1))
在开始TDD之前,我从来没有想过这个。我总是使用第一种方法,仅此而已。但现在我正在为我的附件模型编写测试,我最终做了如下事情:
require 'test_helper'
class AttachmentTest < ActiveSupport::TestCase
test "should be valid" do
resource = build(:attachment)
assert resource.valid?
end
# FIXME is 'attachable' the final name?
test "should require attachable" do
resource = build(:attachment, attachable: nil)
assert resource.invalid?
end
test "should require file" do
resource = build(:attachment, file: nil)
assert resource.invalid?
end
end
不知何故,我正在测试永远不会发生的场景 build(:attachment)
。
所以我的问题是:我应该放弃思考 "I have to do it in order to prove Project.attachments.build()
is gonna work" 吗?
我也在 Project
和 Mission
中进行测试,例如:
- 应该有很多附件
- 应该允许创建附件
- 应该保存附件
- 应该检索附件
这变得令人困惑。
在测试方面,这个关系应该怎么测试?
抱歉这么久了(也许)有点混乱 post。
编辑
问题bonus有没有办法简单的说"we can not create from Attachment and have to go through a relation"
在我看来,您正在尝试测试 rails:
中内置的功能
- 应该有很多附件 = 测试
has_many :attachments
- 应该允许创建附件 = 测试
accepts_nested_attributes_for :attachments
- 应保存附件 =
has_many
的测试autosave
- 应该检索附件 = 再次测试
has_many :attachments
还有,你自己说的:
Somehow, I'm testing scenarios that will never happened build(:attachment)
.
那么何必呢?
您想测试您的对象以确保它们响应 规格。例如,如果你想确保 Attachment
必须有 和 attachable
,那么你可以写:
test 'must have attachable' do
attachment = Attachment.new.tap(&:valid?)
assert_includes(attachment.errors.details[:attachable], { error: :blank })
end
这是,我认为,确保您对属性进行存在验证的最佳选择。
我正在学习 TDD 和 rails。我正在为一个 "logic" 问题伤害自己。先介绍一个情况。
我们有 3 个模型:Project
、Mission
、Attachment
。我是这样创建的
rails g model Mission
rails g model Project
rails g model Attachment title:string attachable:references{polymorphic}
rake db:migrate
什么产生了这个schema.rb
ActiveRecord::Schema.define(version: 20180307200338) do
create_table "attachments", force: :cascade do |t|
t.string "attachable_type"
t.integer "attachable_id"
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["attachable_type", "attachable_id"], name: "index_attachments_on_attachable_type_and_attachable_id"
end
create_table "missions", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "projects", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
对于模型,我们有:
# app/models/mission.rb
class Mission < ApplicationRecord
has_many :attachments, :as => :attachable
end
# app/models/project.rb
class Project < ApplicationRecord
has_many :attachments, :as => :attachable
end
# app/models/attachment.rb
class Attachment < ApplicationRecord
belongs_to :attachable, polymorphic: true
end
现在我们有了上下文,我想介绍一下我的"logic"问题。对我来说,创建一个 Attachment
是完全符合逻辑的:
Mission.find(1).attachments.create(file: 'my-file.jpg')
Project.find(1).attachments.create(file: 'my-file.jpg')
但很难想象自己会创建这样的附件:
Attachment.create(attachable: Mission.find(1))
Attachment.create(attachable: Project.find(1))
在开始TDD之前,我从来没有想过这个。我总是使用第一种方法,仅此而已。但现在我正在为我的附件模型编写测试,我最终做了如下事情:
require 'test_helper'
class AttachmentTest < ActiveSupport::TestCase
test "should be valid" do
resource = build(:attachment)
assert resource.valid?
end
# FIXME is 'attachable' the final name?
test "should require attachable" do
resource = build(:attachment, attachable: nil)
assert resource.invalid?
end
test "should require file" do
resource = build(:attachment, file: nil)
assert resource.invalid?
end
end
不知何故,我正在测试永远不会发生的场景 build(:attachment)
。
所以我的问题是:我应该放弃思考 "I have to do it in order to prove Project.attachments.build()
is gonna work" 吗?
我也在 Project
和 Mission
中进行测试,例如:
- 应该有很多附件
- 应该允许创建附件
- 应该保存附件
- 应该检索附件
这变得令人困惑。
在测试方面,这个关系应该怎么测试?
抱歉这么久了(也许)有点混乱 post。
编辑
问题bonus有没有办法简单的说"we can not create from Attachment and have to go through a relation"
在我看来,您正在尝试测试 rails:
中内置的功能- 应该有很多附件 = 测试
has_many :attachments
- 应该允许创建附件 = 测试
accepts_nested_attributes_for :attachments
- 应保存附件 =
has_many
的测试 - 应该检索附件 = 再次测试
has_many :attachments
autosave
还有,你自己说的:
Somehow, I'm testing scenarios that will never happened
build(:attachment)
.
那么何必呢?
您想测试您的对象以确保它们响应 规格。例如,如果你想确保 Attachment
必须有 和 attachable
,那么你可以写:
test 'must have attachable' do
attachment = Attachment.new.tap(&:valid?)
assert_includes(attachment.errors.details[:attachable], { error: :blank })
end
这是,我认为,确保您对属性进行存在验证的最佳选择。