0
votes

I have the following test:

it "can add an item" do
    item = Item.new("car", 10000.00)
    expect(@manager.add_item("car", 10000.00)).to eq(item)
end

Item's initialize looks like (class has attr_accessor for, type, price, and is_sold):

  def initialize(type, price)
    @type = type
    @price = price
    @is_sold = false
    @@items << self
  end

Manager's add item looks like:

  def add_item(type, price)
    Item.new(type, price)
  end

This test is currently failing because the two items have different object ids, although their attributes are identical. Item's initialize method takes a type, and a price. I only want to check for equality on those features... Is there a way to test strictly for attribute equality?

I have tried should be, should eq, to be, and eql? with no luck.

2
Please post the entire code for the Item class. In the code you've posted type and price are assigned to instance variables and RSpec (or any code outside the instance) has no way to access or compare those values. Does the class have e.g. attr_reader so other code can access them? - Jordan Running
item and @manager.add_item("car", 10000.00)) will be two different instances of the same class Item. If you want to test if the attributes are the same, let i0 = Item.new("car", 10000.00); i2 = Item.new("car", 10000.00), then test i0.type == i1.type, etc., - Cary Swoveland
@Jordan, yes theres an attr_accessor on type and price, will update code to reflect that - coolalligator15
And yes @CarySwoveland, that's true. But they have matching name and type. That's what I am trying to compare in this unit test. - coolalligator15
@Jordan, I'm not sure that's needed, as long as we know there are read accessors. - Cary Swoveland

2 Answers

1
votes

Assuming your class has a public interface for reading those attributes (e.g. attr_reader :type, :price), then the most sensible way is probably to implement a == method:

class Item
  # ...

  def ==(other)
    self.type == other.type &&
      self.price == other.price
  end
end

This allows any two Items to be compared using ==, and so RSpec's eq method will work as expected.

If you don't want your class to have an equality method, your best bet is probably to check each attribute individually:

it "can add an item" do
  expected = Item.new("car", 10000.00)
  actual = @manager.add_item("car", 10000.00)

  expect(actual.type).to eq(expected.type)
  expect(actual.price).to eq(expected.price)
end

But as you can probably tell this may become a maintainability challenge as you add features to Item.

0
votes

I suggest:

it "can add an item" do
  item0 = Item.new("car", 10000.00)
  item1 = @manager.add_item("car", 10000.00)
  expect(item0.name==item1.name && item0.type==item1.type)
end