Rails 3.1, RSpec: тестирование моделей валидации - PullRequest
69 голосов
/ 24 сентября 2011

Я начал свой путь с TDD в Rails и столкнулся с небольшой проблемой, касающейся тестов для валидации моделей, которые, похоже, не могут найти решение.Допустим, у меня есть модель User,

class User < ActiveRecord::Base
  validates :username, :presence => true
end

и простой тест

it "should require a username" do
  User.new(:username => "").should_not be_valid
end

Это правильно проверяет проверку присутствия, но что, если я хочу быть более конкретным?Например, тестирование full_messages для объекта ошибокОн просто говорит: «Ожидается ли верный? Вернуть ложь, получил истину».Тем не менее, второй пример теста имеет небольшой недостаток: он использует метод create вместо нового метода для получения объекта ошибок.

Я бы хотел, чтобы мои тесты были более конкретными в отношении того, что онитестирование, но в то же время не должны касаться базы данных.

Кто-нибудь есть какие-либо входные данные?

Ответы [ 7 ]

96 голосов
/ 24 сентября 2011

Во-первых, я хотел бы сказать, что у вас злое имя.

Во-вторых, ПОЗДРАВЛЕНИЯ по поводу вашего усилия в TDD с ROR Я обещаю, что как только вы начнете, вы не оглянетесь.

Простейшим быстрым и грязным решением будет создание новой действительной модели перед каждым из ваших тестов, например:

 before(:each) do
    @user = User.new
    @user.username = "a valid username"
 end

НО я предлагаю вам настроить фабрики для всех ваших моделей, которые будут генерировать действительную модель длявы автоматически, а затем вы можете запутаться с отдельными атрибутами и посмотреть, если ваша проверка.Мне нравится использовать FactoryGirl для этого:

По существу, после настройки ваш тест будет выглядеть примерно так:

it "should have valid factory" do
    FactoryGirl.build(:user).should be_valid
end

it "should require a username" do
    FactoryGirl.build(:user, :username => "").should_not be_valid
end

Да, а вот хороший Railscast , который объясняет все это лучше меня:

удачи:)


ОБНОВЛЕНИЕ: По состоянию на версия 3.0 Синтаксис для заводской девушки изменился.Я изменил свой пример кода, чтобы отразить это.

42 голосов
/ 01 октября 2011

Более простой способ проверить валидацию моделей (и намного больше активных записей) - использовать драгоценный камень, такой как musta или замечательный .

разрешить для проверки следующим образом:

describe User

  it { should validate_presence_of :name }

end
16 голосов
/ 21 июля 2013

Попробуйте это:

it "should require a username" do
  user = User.create(:username => "")
  user.valid?
  user.errors.should have_key(:username)
end
4 голосов
/ 31 марта 2017

в новой версии rspec, вы должны использовать ожидаемое вместо этого, в противном случае вы получите предупреждение:

it "should have valid factory" do
    expect(FactoryGirl.build(:user)).to be_valid
end

it "should require a username" do
    expect(FactoryGirl.build(:user, :username => "")).not_to be_valid
end
0 голосов
/ 24 апреля 2018

Немного опоздал на вечеринку, но если вы не хотите добавлять совпадения, это должно работать с rspec-rails и factorybot:

# ./spec/factories/user.rb
FactoryBot.define do
  factory :user do
    sequence(:username) { |n| "user_#{n}" }
  end
end

# ./spec/models/user_spec.rb
describe User, type: :model do
  context 'without a username' do
    let(:user) { create :user, username: nil }

    it "should NOT be valid with a username error" do
      expect(user).not_to be_valid
      expect(user.errors).to have_key(:username)
    end
  end
end
0 голосов
/ 05 октября 2017

Как сказал @nathanvda, я бы воспользовался преимуществом Маунт-мачтера Thoughtbot .С этим раскачиванием вы можете написать свой тест следующим образом, чтобы проверить наличие, а также любое пользовательское сообщение об ошибке.

RSpec.describe User do

  describe 'User validations' do
    let(:message) { "I pitty da foo who dont enter a name" }

    it 'validates presence and message' do
     is_expected.to validate_presence_of(:name).
      with_message message
    end

    # shorthand syntax:
    it { is_expected.to validate_presence_of(:name).with_message message }
  end

end
0 голосов
/ 03 апреля 2013

Я традиционно обрабатывал спецификации содержания ошибок в спецификациях функций или запросов. Так, например, у меня есть аналогичная спецификация, которую я приведу ниже:

Пример спецификации объекта

before(:each) { visit_order_path }

scenario 'with invalid (empty) description' , :js => :true do

  add_empty_task                                 #this line is defined in my spec_helper

  expect(page).to have_content("can't be blank")

Итак, моя спецификация модели проверяет, является ли что-то допустимым, но затем моя спецификация, которая проверяет точный вывод сообщения об ошибке. К вашему сведению, эти характеристики требуют Capybara, которую можно найти здесь .

...