如何使用RSpec证明特定实例不再存在?

时间:2019-02-10 13:54:33

标签: ruby object rspec instance

我正在RSpec中编写单元测试,以检查在方法移动或删除之后创建的实例是否不存在。

例如,我有一个Airport类和一个Plane类,而Airport = Airport.new初始化时存储了一个Plane.new实例。当#takeoff方法运行时,Plane.new存储在其他地方或#pop'ped。

我如何证明此Plane.new的确切实例未包含在机场中?有没有办法捕获方法所作用的对象的ID?

我正在考虑的测试将是这样的:

describe Airport do
  it "confirms plane is not there after #takeoff" do
    airport = Airport.new
    airport.takeoff
    expect(airport).not_to include(*ID OF PLANE MOVED/POPPED*)
  end
end

将来,机场可以使用任意数量的飞机进行初始化,因此,我相信有必要使用ID进行确认,但很高兴听到其他消息。

2 个答案:

答案 0 :(得分:3)

通常,单元测试会测试公共API,因此问题应该是:“机场有办法告诉我们地面上有哪些飞机”。如果那是重要的信息,就必须有这样的方法。例如,您可能有一个名为planes的方法,然后仅检查该集合中是否包含特定实例:

expect(airport.planes).not_to include(plane)

另一种方法可能是,该飞机对当前所在的机场进行参考,起飞后将其设置为零。因此,您最终要检查该引用:

expect(plane.airport).to be_nil

但是无论如何,这全都与数据建模有关,而不是与测试框架有关

答案 1 :(得分:1)

这是我的评论中提到的使用object_id的示例。 我的rspec技巧有些生锈,但是希望您能理解。

require 'rspec'

class Plane 
    def initialize(some_property)
        @some_property = some_property
    end
end

class Airport
    attr_reader :planes_ready_for_takeoff, :planes_in_fight
    def initialize()
        @planes_ready_for_takeoff = [Plane.new("plane_foo"), Plane.new("plane_bar")]
        @planes_in_fight = []
    end
    def takeoff()
        @planes_in_fight << @planes_ready_for_takeoff.shift
    end
end

describe "Airport" do
  before(:context) do 
    @airport =  Airport.new 
    @first_plane = @airport.planes_ready_for_takeoff.first
  end
  it "confirms a plane is ready for takeoff" do
    expect(@airport.planes_ready_for_takeoff.map { |p| p.object_id}).to include(@first_plane.object_id)
end
describe "#takeoff" do 
    it "remove the first plane from the list of planes ready to take off" do 
        @airport.takeoff 
        expect(@airport.planes_ready_for_takeoff.map { |p| p.object_id}).not_to include(@first_plane.object_id)
    end
  end
end

顺便说一句,我认为您甚至不需要映射到object_id,因为我认为include使用==应该检查确切的对象。