2014-06-22 33 views
0

我正在写一个程序,允许用户匹配交易中的订单,最终在它们之间传递事物。rspec平等匹配失败,对象看起来是一样的

我有一个类,TransferAsset,这需要一个事务,并创建了一个资产进行交易的买方:

class TransferAsset 
    attr_accessor :transaction, :seed_asset 

    def initialize(opts = {}) 
    @transaction = opts[:transaction] 
    end 

    def create_seed_asset 
    @seed_asset = UserInventoryFactory.new({transaction: transaction}).inventory 
    end 
end 

这里的UserInventory类:

class UserInventoryFactory 
    attr_accessor :transaction, :inventory 

    def initialize(opts = {}) 
    @transaction = opts[:transaction] 
    create_user_inventory 
    set_values 
    end 

    def set_values 
    set_seed_transaction 
    set_owner 
    set_amount 
    set_purchase_date 
    set_initial_amount 
    end 

    def create_user_inventory 
    @inventory = UserInventory.new 
    end 

    def set_seed_transaction 
    inventory.seed_transaction_id = transaction.id 
    end 

    def set_owner 
    inventory.user_id = transaction.buyer_id 
    end 

    def set_amount 
    inventory.amount = transaction.amount 
    end 

    def set_purchase_date 
    inventory.purchase_date = transaction.created_at.beginning_of_day 
    end 

    def set_initial_amount 
    inventory.initial_amount = transaction.amount 
    end 

end 

我有一个RSpec测试的TransferAsset等级:

describe '#create_seed_asset' do 
    it 'creates an asset for the purchaser' do 
    factory = UserInventoryFactory.new({transaction: transaction}) 
    expect(transfer.create_seed_asset).to eql factory.inventory 
    end 
end 

测试失败,因为:

1) TransferAsset#create_seed_asset creates an asset for the purchaser 
Failure/Error: expect(transfer.create_seed_asset).to eql factory.inventory 

    expected: #<UserInventory id: nil, amount: 5000.0, initial_amount: 5000.0, purchase_date: "2014-06-22 05:00:00", user_id: 2, seed_transaction_id: 1, created_at: nil, updated_at: nil> 
     got: #<UserInventory id: nil, amount: 5000.0, initial_amount: 5000.0, purchase_date: "2014-06-22 05:00:00", user_id: 2, seed_transaction_id: 1, created_at: nil, updated_at: nil> 

    (compared using eql?) 

我已经尝试了所有的RSpec的平等匹配器,它总是失败,这让我觉得我写不好的代码,无论是在我的测试,或在我的实际类。

我在做什么错,或者我能做得更好?

回答

2

您需要为您的课程覆盖平等方法。现在,它比较对象id并且因为它们在内存中不是同一个对象,所以它总是假的。

尝试压倒一切的==来比较两个对象

的==新的类,忽略继承的默认行为,是比较对象ID

1

您正在尝试比较两个实例变量UserInventory类的不同实例中,每个在create_user_inventory方法创建:

def create_user_inventory 
    @inventory = UserInventory.new 
end 

两相比较,给你假的,就像下面:

Object.new.eql? Object.new 
# => false 

有相同类别的两个对象(甚至相同的属性值),不使他们平等的,你不能指望默认的比较方法知道他们是。

像字符串,数组和地图这样的对象都有自定义语义的比较器实现,如果你希望你的类有自己的语义 - 你还应该实现自定义比较器并定义这些语义。

here参见:

红宝石主要有三个平等的测试方法,==eql?equal?。这些方法通常位于Object类中,因为所有其他类都从Object继承,所以它们自动获得这三种方法的访问权限。在Object类内部,所有的方法都是完全相同的 ,它们测试两个对象是否完全相同的对象。 也就是说,两个对象必须具有相同的对象ID。

+0

不知道我明白。假设我做了以下操作:'a ='string'','b ='string''。现在,'a == b#=> true',但是,'a.object_id!= b.object_id#=> true'。在这种情况下,两个不同的对象通过'=='被认为是相同的,而不具有相同的对象ID。这与你写的是否矛盾? – garythegoat

+0

@garythegoat - 不,因为String实现_overrides_的==行为 - 请参见[here](http://ruby-doc.org//core-2.2.0/String.html#method-i-3D- 3D) –

+0

哦,很酷,谢谢! – garythegoat

0

既然你只是想测试对象等价,你可以将你的对象转换为JSON并比较结果。

它避免了必须重新定义平等方法。所以你可以改变你的测试看起来像这样:

describe '#create_seed_asset' do 
    it 'creates an asset for the purchaser' do 
    factory = UserInventoryFactory.new({transaction: transaction}) 
    expect(transfer.create_seed_asset.to_json).to eql factory.inventory.to_json 
    end 
end