我刚开始使用Ruby和Rspec,所以如果我不是非常具体,我会提前为我的错误语法道歉。
我有两个班级,机场和天气,应该沟通,所以我可以在机场的天气中调用stormy?
方法。我想做的是在天气恶劣时停止飞机起飞。
我已经定义了bad_weather
方法,但它不起作用
这是我的代码:
我在Rspec的考试
describe Airport do
it ' does not allow planes to take off with stormy weather' do
subject.take_off double(:plane)
expect {(weather).to be_stormy?}.to raise_error "Flight cancelled due to bad weather"
end
end
我想从
获取方法的课程class Weather
def stormy?
roll >= 6
end
private
def roll
rand(10)
end
end
我要在
中调用该方法class Airport
DEFAULT_CAPACITY = 10
def initialize
@planes = []
@capacity = DEFAULT_CAPACITY
end
def take_off(plane)
fail "Flight cancelled due to bad weather" if bad_weather?
@planes.pop
end
def bad_weather?
weather = Weather.new
weather.stormy?
end
end
我知道我的Rspec测试很糟糕,任何帮助都会受到赞赏。
答案 0 :(得分:3)
当您遇到被测对象依赖其他对象的情况时,您希望控制这些对象。在您的方案中,您希望控制weather
知道的airport
。
为了做到这一点,你需要强制它,当你问stormy?
它时,它会返回true
。这样你就可以确保你对Airport
类进行单元测试,并且所有对其他对象的依赖都在控制之中。
我将如何做到这一点:
class Airport
DEFAULT_CAPACITY = 10
def initialize
@planes = []
@capacity = DEFAULT_CAPACITY
end
def take_off(plane)
fail "Flight cancelled due to bad weather" if bad_weather?
@planes.pop
end
def bad_weather?
weather.stormy?
end
def weather
@weather ||= Weather.new
end
end
然后在您的测试中,您将通过这样做控制您的机场weather
:
it 'does not allow planes to take off with stormy weather' do
my_airport = Airport.new
stormy_weather = Weather.new
allow(stormy_weather).to receive(:is_stormy?) { true }
allow(my_airport).to receive(:weather) { stormy_weather }
expect(my_airport.take_off("Boeing")).to raise_error "Flight cancelled due to bad weather"
end
@SteveTurczyn答案也有效。我个人不喜欢它,因为你不只是让机场的天气暴风雨,而是任何Weather
实例。
答案 1 :(得分:0)
测试此方法的技巧是强制#stormy?
为真,然后测试take_off方法调用是否会引发错误。
it 'does not allow planes to take off with stormy weather' do
allow_any_instance_of(Weather).to receive(:stormy?).and_return(true)
my_airport = Airport.new
expect(my_airport.take_off("Boeing")).to raise_error "Flight cancelled due to bad weather"
end
顺便提一下,您还要测试条件的反函数,因此另一项测试将非常有用。
it 'does not complain about bad weather if weather is good' do
allow_any_instance_of(Weather).to receive(:stormy?).and_return(false)
my_airport = Airport.new
expect(my_airport.take_off("Boeing")).not_to raise_error "Flight cancelled due to bad weather"
end