【问题标题】:How can I prove that a specific instance no longer exists using RSpec?如何使用 RSpec 证明特定实例不再存在?
【发布时间】:2019-02-10 13:54:32
【问题描述】:

我正在 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

未来,Airport 可以用任意数量的飞机初始化,所以我相信有必要使用 id 来确认,但我很乐意听到其他情况。

【问题讨论】:

标签: ruby object rspec instance


【解决方案1】:

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

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

另一种方法可能是飞机有一个参考它现在所在的机场,起飞后它会被设置为零。所以你最终会检查那个参考:

expect(plane.airport).to be_nil

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

【讨论】:

    【解决方案2】:

    这是一个使用我评论中提到的 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 使用 == 应该检查确切的对象。

    【讨论】:

    • 鉴于该属性存在且是公开的,只需expect(@airport.planes_ready_for_takeoff).to include(@first_plane),无需检查ID。
    • 是的,我只是想将其添加为评论
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多