使用Rspec(Rails)进行Paperclip上传的单元测试

24

我完全不懂 Rspec。今晚写我的第一个测试。

我有一个名为 Image 的模型。使用 paperclip 我附加了一个名为 photo 的文件。标准的事情。我运行了 paperclip 生成器,在生产和测试模式下一切都正常。

现在我有一个名为 image.rb 的 spec 文件,它看起来像这样(它是通过 ryanb 的 nifty_scaffold 生成器创建的):

require File.dirname(__FILE__) + '/../spec_helper'

describe Image do

  it "should be valid" do
    Image.new.should be_valid
  end
end

这个测试失败了,我意识到是因为我的模型验证(即validates_attachment_presence)的问题。

我得到的错误是:

Errors: Photo file name must be set., Photo file size file size must be between 0 and 1048576 bytes., Photo content type is not included in the list

那么我如何告诉rspec在运行我的测试时上传一张照片呢?

我猜这可能与fixtures有关...也许不是。 我尝试过对它们进行一些调整,但没有成功。 就记录而言,我已经在我的fixtures文件夹中创建了一个名为images的文件夹,我想在我的测试中使用的两个文件分别为rails.png和grid.png)

我尝试了以下操作:

it "should be valid" do
  image = Image.new :photo => fixture_file_upload('images/rails.png', 'image/png').should be_valid 

  # I've also tried adding stuff like this
  #image.stub!(:has_attached_file).with(:photo).and_return( true )
  #image.stub!(:save_attached_files).and_return true
  #image.save.should be_true  
end
但是Rspec抱怨无法识别“fixture_file_upload”...我打算去买那本Rspec书。 我在网上搜寻答案,但似乎找不到任何东西。如果我从模型中删除验证,我的测试数据库确实会填充一些数据,所以我知道它的某些部分可以正常工作。
提前致谢,
编辑:
images.yml看起来像这样:
one:
  name: MyString
  description: MyString

two:
  name: MyString
  description: MyString
4个回答

39

这应该适用于Rails 2.X:

Image.new :photo => File.new(RAILS_ROOT + '/spec/fixtures/images/rails.png')

从Rails 3开始,不再使用RAILS_ROOT,而应该使用Rails.root

以下代码可用于Rails 3:

Image.new :photo => File.new(Rails.root + 'spec/fixtures/images/rails.png')

一定要买 RSpec 这本书,它太棒了。


如果模型没有“photo”字段怎么办?它仍然可以正常工作吗?我在我的spec/factories.rb文件中有这个:comment.pic File.new(RAILS_ROOT + '/spec/fixtures/images/rails.png')但是我得到了RSpec错误:ActiveRecord::RecordInvalid in 'Comment should create a new instance given valid attributes'Validation failed: Pic file name image is required - nnyby
2
我猜想你在模型中放置的任何内容都应该替换掉:photo,所以如果你写了has_attached_file :donkey,那么你就需要写Image.new :donkey => File.new等。 - Ruxton
谢谢你的回答。我使用相对路径 File.new('spec/fixtures/images/rails.png') 而不是 root,而且在我的测试中它完全正常。 - Amin Ariana
如果你使用的是app/assets/images中的照片,而不是spec/fixtures/images中的照片,会怎样呢?我正在使用app/assets/images,但实际上照片被上传了,这很奇怪...然后它出现在我的public/system照片中,这不是我想要的。我该怎么办? - Jwan622

19

Rails.root是一个路径名对象,因此您可以像这样使用它:

Image.new :photo => Rails.root.join("spec/fixtures/images/rails.png").open

编辑 - 可能在Rails 3中无效...

  • 请参考@Paul Rosania的答案。

5
在Google搜索中,如果有其他人发现这篇文章,需要知道RAILS_ROOT在Rails 3.0中已不再有效。应该将该行代码修改为:
Rails.root
Image.new :photo => File.new(Rails.root + 'spec/fixtures/images/rails.png')

(请注意缺少前导斜杠!)

4
你可能在想:“为什么要使用#join,因为我知道分隔符总是斜杠?”- 但如果你使用File join而不是+,无论你是否忘记并在第二个路径中放置一个前导斜杠在“spec”之前,你都会得到有效的路径。 - Steve

1

我在我的集成测试中使用multipart_body宝石。它比测试更符合BDD。

http://steve.dynedge.co.uk/2010/09/19/multipart-body-a-gem-for-working-with-multipart-data/

关于rspec和paperclip,has_attached_file:photo指令创建了一种虚拟属性,即:photo...当您将文件或路径分配给照片时,paperclip接管并存储文件,可选择对其进行处理,例如自动创建缩略图、导入电子表格等。您没有告诉rspec测试paperclip。您正在调用代码并告诉rspec该代码的结果应该是什么。
在$GEM_HOME/gems/paperclip-2.3.8/README.rdoc中,在文件的76%左右,特别是第147和148行下的==后处理:
---[ BEGIN QUOTE ]--- 注意:因为处理器通过将原始附件转换为样式来运行,如果没有定义样式,则不会运行任何处理器。 ---[ END QUOTE ]---
阅读代码,您将看到支持:original...您的has_attached_file是否定义了样式?

我使用了一个通用的":styles => { :original => { :this_key_and => :this_value_do_not_do_anything_unless_a_lib_paperclip_processors__foo_dot_rb__does_something_with_them } }" ...只是为了让Paperclip将文件从某些临时目录移动到我的has_attached_file:path中。

人们可能认为这在文档中应该是默认或更明显的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接