Dmitry Frank
Dmitry Frank

Reputation: 10757

Ruby on rails: write correct unit test

I'm reading "Agile Web Development with Rails" and I can't understand a unit test.

There's a model defined like this:

class Product < ActiveRecord::Base
  # .....
  validates :price, numericality: {greater_than_or_equal_to: 0.01}
  # .....
end

And the test:

  test "product price must be positive" do
    product = Product.new(
      title: "my title",
      description: "yyy",
      image_url: "zzz.jpg",
    )

    product.price = -1
    assert product.invalid?
    assert_equal ["must be greater than or equal to 0.01"],
      product.errors[:price]

    product.price = 0
    assert product.invalid?
    assert_equal ["must be greater than or equal to 0.01"],
      product.errors[:price]

    product.price = 1
    assert product.valid?

  end

Why would we need this:

    assert_equal ["must be greater than or equal to 0.01"],
      product.errors[:price]

Why compare error messages? Instead of writing a test like this:

product.price = -1
assert product.invalid?, "must be greater than or equal to 0.01"

product.price = 0
assert product.invalid?, "must be greater than or equal to 0.01"

Upvotes: 1

Views: 261

Answers (2)

Dmitry Frank
Dmitry Frank

Reputation: 10757

As far as I understood, the author of the book really wanted to verify that the error message is the one he expected.

It seems to me a really bad idea to hardcode an error message, since it might be changed in the next framework version.

Upvotes: 1

Billy Chan
Billy Chan

Reputation: 24815

object.errors is a blank hash. When saving/updating an ActiveModel instance, if validation fails, the error will be added to specific key matching the attributes, like:

{ price: "must be...", name: "can't be blank", ...}.

In this case it's the "price" which failed validation. So the errors object is

{ price: "must be greater than or equal to 0.01"}

To access the message string. You need to the failed attribute as the key, like errors[:price]

Upvotes: 0

Related Questions