Rails RSpec单元测试对用户属性,图像文件类型失败

时间:2016-11-01 17:16:55

标签: ruby-on-rails unit-testing rspec carrierwave

我尝试了几种不同的方法,并且不清楚为什么我写的用户单元测试的各种排列仍然无法测试用户对象的图像属性的文件类型。

这是我现在拥有的......

模型/ user.rb

@model AssignerWebTool.Models.CreateUserModel
@{
ViewBag.Title = "Create User";
}
<head>
<title></title>

<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
</head>

<body>
<script type="text/javascript">
$(document).ready(function () {
$("help").select2();
});
</script>

<select id="help" class="help">
    <option value="AL">Alabama</option>
    <option value="WY">Wyoming</option>
</select>
</body>

上传/ image_uploader.rb

class User < ApplicationRecord
  mount_uploader :image, ImageUploader
  validate :image_size_validation
  validates_format_of :image, with: %r{\.(png|jpg|jpeg)\Z/}i, message: "image must be png, jpg, or jpeg", allow_nil: true

  def image_size_validation
    errors[:image] << "should be less than 5MB" if image.size > 5.megabytes
  end
end

规格/模型/ user_spec.rb

class ImageUploader < CarrierWave::Uploader::Base
  def extension_white_list
    %w(jpg jpeg gif png)
  end
end

令人费解的是,如果我没有指定 let(:user) { FactoryGirl.create(:user, username: "zoidberg", image: "image.png") } it "has a valid image file" do expect(user).to be_valid expect(user.image).to be_valid expect(FactoryGirl.build(:user, username: "Farnsworth", image: "image.jpg")).to be_valid end ,那么测试将失败username: <something>,尽管它在其他所有测试中都有效并且已经在工厂内构建。

规格/工厂/ user.rb

Username is invalid

我也尝试了这个FactoryGirl.define do factory :user do first_name Faker::Name.first_name last_name Faker::Name.last_name sequence(:username) { |n| "#{n}#{Faker::Internet.user_name}#{Faker::Number.number(5)}#{Faker::Hipster.word}" } sequence(:email) { |n| "#{n}#{Faker::Hipster.word}#{Faker::Number.number(5)}#{Faker::Internet.email}" } phone Faker::Base.numerify('##########') password Faker::Internet.password(6, 20) state Faker::Address.state_abbr city Faker::Address.city image Faker::Avatar.image sequence(:zip) { |n| "#{n}#{n}#{n}#{n}#{n}" } seeking_coach true accept_email true accept_phone true end end ,我认为它会起作用,但显然不会。

1 个答案:

答案 0 :(得分:0)

您无法通过简单地使用字符串来表示文件来测试carrierwave - &#34; image.png&#34;。您实际上需要打开文件并将其上传。

File.open(path_to_file) { |f| user.image.store!(f) }

其中path_to_file表示包含您正在测试的文件的文件名的完整路径。

这就是为什么shoulda匹配器也不起作用的原因:

it { should have_valid(:image).when('image.jpg', 'image.png', 'image.jpeg')} # won't work

您需要编写单独的测试来检查每种文件类型。

此外,您应该构建用户对象 - 而不是创建用户对象,因为它在此阶段没有获得有效图像:

let(:user) { FactoryGirl.build(:user, username: "zoidberg") }

it 'with png file it should be valid' do
  path_to_png_file = Rails.root + "spec/files/image.png"
  File.open(path_to_png_file) { |f| user.image.store!(f) }
  expect(user).to be_valid
end

it 'with txt file it should be invalid' do
  path_to_txt_file = Rails.root + "spec/files/text.txt"
  File.open(path_to_txt_file) { |f| user.image.store!(f) }
  expect(user).to_not be_valid
end

当然,您需要根据测试环境设置路径。

您不需要测试实际图像本身 - 它实际上只是您有验证用户的属性。如果图像无效,则用户无效,但您可以测试验证错误,以确保它们与图像相关,如果您愿意。