说明是这样的:
按照清单11.68中的模板,在第11.4节中编写一个图像上传器的测试。作为准备,您应该将图像添加到fixtures目录(使用,例如,cp app / assets / images / rails.png test / fixtures /)。 (如果您正在使用Git,我还建议您更新.gitignore文件,如清单11.69所示。)为了避免混淆错误,您还需要配置CarrierWave以通过创建初始化文件来跳过测试中的图像大小调整,如图所示代码清单11.70清单11.68中的附加断言检查主页上的文件上载字段和有效提交产生的微博上的有效图像属性。请注意使用特殊的fixture_file_upload方法将文件作为fixture内的夹具上传.2提示:要检查有效的图片属性,请使用第10.1.4节中提到的assigns方法在有效提交后访问创建操作中的微博。< / p>
这是我在test / integration / micrposts_interface_test.rb
中的代码 test "micropost interface" do
log_in_as(@user)
get root_path
assert_select 'div.pagination'
assert_select 'input[type=FILL_IN]'
# Invalid submission
assert_no_difference 'Micropost.count' do
post microposts_path, micropost: { content: "" }
end
assert_select 'div#error_explanation'
# Valid submission
content = "This micropost really ties the room together"
picture = fixture_file_upload('test/fixtures/rails.png', 'image/png')
assert_difference 'Micropost.count', 1 do
post microposts_path, micropost: { content: content, picture: FILL_IN }
end
assert FILL_IN.picture?
follow_redirect!
assert_match content, response.body
# Delete a post.
assert_select 'a', text: 'delete'
first_micropost = @user.microposts.paginate(page: 1).first
assert_difference 'Micropost.count', -1 do
delete micropost_path(first_micropost)
end
# Visit a different user.
get user_path(users(:archer))
assert_select 'a', text: 'delete', count: 0
end
在assert_select'input [type = FILL_IN]'中,我的填写是type = file
在post microposts_path,micropost:{content:content,picture:FILL_IN}中,我的填写是图片:true
断言FILL_IN.picture?是@ user.microposts.picture?
我得到的错误是: NoMethodError:NoMethodError:未定义的方法`picture?'对于#
所以我认为我的前两个FILL_IN是正确的。问题来自第三次填写。我写了@ user.microposts因为我想测试图片的存在吗?它必须在用户的微博上。但这个错误不是图片的方法吗?
我也试过了@ user.micropost.picture ?,错误是NoMethodError:NoMethodError:未定义的方法`micropost'代表#
我认为我的推理线是正确的,但显然不是。救命!我是一个完整的新手。
答案 0 :(得分:4)
我的解决方案,似乎有效:
test "micropost interface" do
log_in_as(@user)
get root_path
assert_select 'div.pagination'
assert_select 'input[type=file]'
# Invalid submission
assert_no_difference 'Micropost.count' do
post microposts_path, micropost: { content: "" }
end
assert_select 'div#error_explanation'
# Valid submission
content = "This micropost really ties the room together"
picture = fixture_file_upload('test/fixtures/sample-image.jpg', 'image/jpg')
assert_difference 'Micropost.count', 1 do
post microposts_path, micropost: { content: content, picture: picture }
end
assert assigns(:micropost).picture?
assert_redirected_to root_url
follow_redirect!
assert_match content, response.body
# Delete a post.
assert_select 'a', text: 'delete'
first_micropost = @user.microposts.paginate(page: 1).first
assert_difference 'Micropost.count', -1 do
delete micropost_path(first_micropost)
end
# Visit a different user.
get user_path(users(:archer))
assert_select 'a', text: 'delete', count: 0
end
答案 1 :(得分:3)
回答这个问题的时间不多,但也许这会帮助其他人。我为每个人提供了长短的答案,如果你想要快速解释,请在问题的最后阅读TLDR,如果你想要更多的解释,请随时阅读:)
1)assert_select&#39;输入[type = FILL_IN]&#39;
使用任一文件或&#34;文件&#34;将通过测试。根据assert_select的文档:link,&#34;选择器可以是CSS选择器表达式(String),带替换值的表达式,或HTML :: Selector对象。&#34;从本质上讲,它只需要一个有效的CSS选择器,根据这个stackoverflow帖子:link,根据情况而定(如果它是一个字母数字字符串,通常不需要它,就像这里的情况一样,它可能需要也可能不需要引号,但通常使用它们是好的做法,这样就不会出现混淆/错误。
TLDR:使用&#39;输入[type =&#34; file&#34;]&#39;或者&#39;输入[type = file]&#39;在这种情况下会起作用,但使用引号通常被认为是避免错误的好习惯。
2)发布microposts_path,micropost:{content:content,picture:FILL_IN}
对于这个,正如@Nick所提到的,你可能只想使用变量&#39; picture&#39;这是在assert_difference行上方创建的。请记住,当您将图片属性添加到微博模型时,您运行了命令:
rails generate migration add_picture_to_microposts picture:string
这意味着它在创建微博时期望你传递一个字符串,而不是一个布尔值。还要注意测试实际上在做什么:
assert_difference 'Micropost.count', 1 do
post microposts_path, micropost: { content: content, picture: FILL_IN }
end
代码实际上是通过发布到微博路径创建微博,然后检查以确保计数增加1.
现在,您可能会说:但图片变量不是字符串!这是事实,我不是CarrierWave的专家,我还没有真正挖掘它的代码,但似乎它实际上期待文件路径和MIME(文件扩展名)类型,基于fixture_file_upload的文档,可在此处找到:link。如果您还记得本教程,则添加以下行:
mount_uploader :picture, PictureUploader
到您的微博模型,它似乎将图片属性与PictureUploader类(在app / uploaders / picture_uploader.rb中找到)相关联,该类在类文件中包含以下内容:
class PictureUploader < CarrierWave::Uploader::Base
这意味着它继承自CarrierWave :: Uploader :: Base类,这可能意味着CarrierWave正在使用picture属性来处理除字符串以外的东西(正如我所提到的,它似乎需要一个基于文档的路径和MIME类型),但布尔值不会起作用。 (为了记录,我做了一些测试,传递一个随机字符串,然后传递一个随机文件路径,并且都按预期失败 - 所以传递布尔值也是如此。)
此外,并且无可否认它是一个小细节,但即使传入一个布尔值有效,它通常只会测试它是一张图片,而不是特定的图片,这将是另一个使用图片变量。
TLDR:您应该只使用图片变量:post microposts_path,micropost:{content:content,picture:picture}
3)断言FILL_IN.picture?
你提到你使用过代码:
@user.microposts.picture?
得到NoMethodError。原因是@ user.microposts将返回一个微博集合,而不是单个微博,因此它很混乱(具体来说,它返回一个ActiveRecord_Associations_CollectionProxy,它没有图片?方法,因此,你得到一个NoMethodError另外,不要忘记,您可以打开rails控制台,并运行User.first.microposts.class以找出@ user.microposts返回的对象类型。还记得那张照片吗?方法仅适用于单个微博,因此您需要执行以下操作:
@user.microposts.first.picture?
将检查最近创建的微博(微博按照它们创建的日期/时间排序,最新的是第一个)用于图片。
但是,还有另一种方法可以实现,它使用了Hartl在练习中给出的提示:&#34;要检查有效的图片属性,请使用第10.1.4节中提到的分配方法来访问有效提交后的创建操作中的微博&#34;
如果您还记得,可以使用assignign方法从控制器访问实例变量。微博控制器中的创建动作有一个实例变量@micropost,它也是用户创建的最新微博。
代码如下:
foo = assigns(:micropost)
assert foo.picture?
事实上,您可以通过添加以下代码向自己证明这两种方法都有效:
foo = assigns(:micropost)
assert foo.picture?
assert @user.microposts.first.picture?
assert_equal foo, @user.microposts.first
所以这段代码的作用如下:首先,它创建一个变量foo并为其分配新创建的微博。然后检查foo.picture?是的,然后检查另一个方法,@ user.microposts.first.picture?并检查它是否也是真的。最后,它检查foo和@user的最新微博是否相同,所有这些测试都应该通过。
TLDR:你在说这张照片?微博集合的方法,而不是单个微博。你可以使用@ user.microposts.first.picture吗?或者,如果您想使用assigns()方法,您也可以使用它,并使用以下内容:
foo = assigns(:micropost)
assert foo.picture?
希望有所帮助!
答案 2 :(得分:2)
我相信第一个FILL_IN应该读type="file"
来检查这样的输入是否可用。
对于第二个FILL_IN,我认为解决方案是{ content: content, picture: picture }
,其中最后一张&#39;图片&#39;指的是上面两行(你定义这个变量)。
他们和最后一次FILL_IN我不确定。考虑到Hartl提供的暗示,我认为它应该是:
plaatje = assigns(:micropost)
assert plaatje.picture?
但我也是新手并且遵循教程,所以我可能错了。如果有效,请告诉我。
使用这些解决方案,完整代码为:
test "micropost interface" do
log_in_as(@user)
get root_path
assert_select 'div.pagination'
assert_select 'input[type="file"]'
# Invalid submission
assert_no_difference 'Micropost.count' do
post microposts_path, micropost: { content: "" }
end
assert_select 'div#error_explanation'
# Valid submission
content = "This micropost really ties the room together"
pict = fixture_file_upload('test/fixtures/rails.png', 'image/png')
assert_difference 'Micropost.count', 1 do
post microposts_path, micropost: { content: content, picture: pict }
end
plaatje = assigns(:micropost)
assert plaatje.picture?
assert_redirected_to root_url
follow_redirect!
assert_match content, response.body
# Delete a post.
assert_select 'a', text: 'delete'
first_micropost = @user.microposts.paginate(page: 1).first
assert_difference 'Micropost.count', -1 do
delete micropost_path(first_micropost)
end
# Visit a different user.
get user_path(users(:archer))
assert_select 'a', text: 'delete', count: 0
end
答案 3 :(得分:0)
第三个FILL_IN实际上可以使用以下方式填写: @ user.microposts.first.picture? 您的第一个解决方案不起作用,因为您必须指定要查询的微博。