You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DockingStation类中调用Bike类的broken?方法,实现不发放损坏自行车功能并通过RSpec测试

问题:RSpec测试未触发预期异常(无法过滤损坏自行车)

现有代码

DockingStation & Bike 实现

class DockingStation
  attr_reader :bikes, :capacity
  attr_accessor :capacity
  DEFAULT_CAPACITY = 20

  def initialize(capacity = DEFAULT_CAPACITY)
    @bikes = []
    @capacity = capacity
  end

  def release_bike
    fail 'No bikes available' if empty?
    @bikes
  end

  def dock(bike)
    fail 'bike full' if full?
    @bikes << bike
  end

  def full?
    @bikes.count >= DEFAULT_CAPACITY
  end

  def empty?
    @bikes.empty?
  end

  private :full? , :empty?
end

class Bike
  def working?
    true
  end

  def report_broken
    @broken = true
  end

  def broken?
    @broken
  end
end

RSpec 测试

require './lib/docking_station.rb'
require './lib/bike.rb'

describe DockingStation do
  describe 'initialization' do
    subject{DockingStation.new}
    let(:bike) {Bike.new}
    it 'default capacity' do
      described_class::DEFAULT_CAPACITY.times do
        subject.dock(bike)
      end
      expect{ subject.dock(bike) }.to raise_error 'bike full'
    end
  end

  it 'has a default capacity' do
    expect(subject.capacity).to eq DockingStation::DEFAULT_CAPACITY
  end

  describe '#release_bike' do
    it 'releases a bike' do
      bike = Bike.new
    end

    it 'raises an error if bike is broken' do
      bike = Bike.new
      bike.report_broken
      subject.dock bike
      expect {subject.release_bike}.to raise_error 'No bikes available'
    end
  end
end

问题描述

我希望上述RSpec测试能够通过,但始终收到「未触发预期异常」的错误。我的目标是让DockingStation不发放已通过report_broken方法标记为损坏的自行车,但broken?方法定义在Bike类中,因此无法在DockingStation的release_bike方法中直接编写fail 'bike broken' if broken?,因为DockingStation无法识别该方法。恳请提供正确的解决方向,帮助我实现需求并通过测试。


解决方案

问题根源分析

你的测试失败有两个核心原因:

  1. release_bike方法当前只是返回整个@bikes数组,既没有移除要发放的自行车,也没有检查自行车是否损坏;
  2. full?方法硬编码使用了DEFAULT_CAPACITY,忽略了初始化时传入的自定义容量,这会导致初始化容量的测试逻辑潜在失效。

代码修改步骤

1. 修复DockingStation类的核心逻辑

修改release_bike和full?方法,让停靠站能识别并过滤损坏的自行车:

class DockingStation
  # ... 保留原有其他代码 ...

  def release_bike
    # 找到第一辆未损坏的自行车
    available_bike = @bikes.find { |bike| !bike.broken? }
    fail 'No bikes available' unless available_bike
    # 从停靠站中移除这辆自行车并返回
    @bikes.delete(available_bike)
    available_bike
  end

  def full?
    # 使用实例的@capacity而不是默认常量,支持自定义容量
    @bikes.count >= @capacity
  end

  # ... 保留原有其他代码 ...
end

2. 完善RSpec测试的断言逻辑

原测试中it 'releases a bike'没有任何断言,需要补充验证逻辑;同时确保损坏自行车的测试场景正确:

describe DockingStation do
  # ... 保留原有初始化相关测试 ...

  describe '#release_bike' do
    let(:working_bike) { Bike.new }
    let(:broken_bike) { Bike.new.tap(&:report_broken) }

    it 'releases a working bike' do
      subject.dock(working_bike)
      released_bike = subject.release_bike
      expect(released_bike).to be_a(Bike)
      expect(released_bike.working?).to be true
      # 验证自行车已从停靠站移除
      expect(subject.bikes).not_to include(released_bike)
    end

    it 'raises an error if only broken bikes are available' do
      subject.dock(broken_bike)
      expect { subject.release_bike }.to raise_error 'No bikes available'
    end

    it 'raises an error if no bikes are available' do
      expect { subject.release_bike }.to raise_error 'No bikes available'
    end
  end
end

关键逻辑说明

  • 在release_bike中,我们通过@bikes.find { |bike| !bike.broken? }遍历停靠站中的自行车,筛选出第一辆未损坏的;如果没有找到,就抛出错误。
  • 使用@bikes.delete(available_bike)确保发放的自行车从停靠站中移除,符合真实场景的"释放"逻辑。
  • full?方法改用实例变量@capacity,保证初始化时传入的自定义容量能正常生效。

这样修改后,你的测试就能正确触发预期异常,同时停靠站也能实现只发放可用自行车的需求。

内容的提问来源于stack exchange,提问作者hibscodes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 22:02:45