https://relishapp.com/rspec/rspec-mocks/v/3-7/docs/basics/test-doubles
你有一个问题,如果想为程序添加一个信用卡程序用于自己挣钱。测试信用卡函数很难。你不像在测试时,真来一个信用卡购买。而且网络远程调用很慢。
或者你有另一个问题。你想要使用模块设计来开发代码。你想要你的测试尽可能的和其他相关的部分的代码隔离开。 比如你有一个业务逻辑会调用一个model,但是你的测试不想用这个model,你想要你的workflow test有效,但和这个model无关,假定这个model不存在或坏掉。
解决以上问题的方案是a test double.这是一个fake object,在自动化测试中用于取代一个真实的object。所谓假fake,就是这个对象不是一个真实的implementation工具。但是它可以取代那些已装罐的values,并可以返回对指定信息的回复。
Test double也有小issue,作者会给出解释,怎么用自己决定。
开始讲运作方式,(使用rspec-mocks library),然后讨论不同的方法使用来解决上面的2个问题,最后在12章Minitest,会讲解相关用法。
- Test doubles defined✅
- creating Stubs✅
- Mock Expectations✅
- Using Mocks to simulate database Failure✅
- Using Mocks to Specify behavior✅
- More expectation annotations注释简单看了
- Mock Tips(窍门,a useful piece of advise) 简单看了
Test Doubles Defined
a fake是一个典型的Ruby对象,被专门设计用于测试的。
A stub是一个fake,针对一个方法调用返回预先决定的值,而不是在一个实际的对象调用实际的方法。
使用double方法创建a stub 桩件。或者创建一个partial stub通过使用特殊的方法在一个已存在的对象中:
allow(thing).to receive(:name).and_return("Fred")
解释:调用thing.name,得到Fred作为结果
重点是,thing.name方法默认是没有touched(我的理解是被建立),所以无论真实方法会返回什么值都无关重要。Fred作为回复来自于stub,而stub不是真实的对象。
A mock 驭件:stub类似,但是还会返回the fake value。一个mock对象建立一个可测试的期待。如果这个方法没有被调用,mock会发出测试失败信息。用expect取代allow
expect(thing).to recceive(:name).and_return( "Fred" )
使用mock,然后调用thing.name, 仍会得到Fred并且thing.name方法也untouched.
区别:
但是在测试中,如果你不调用thing.name,测试会失败并提供一个error信息。
Creating Stubs
A stub用于取代一个对象的全部或部分,防止一个普通的方法调用发生,作为替代当stub被创建时返回一个预制的value。
RSpec,有2个类型的stubs。full doubles, partical doubles.
a partical double 在什么情况下使用:创建一个对象但有几个方法想要bypass。
a full double使用范围:当测试时,你的代码和a specific API一起工作,而不是一个对象的时候。
Full Doubles (mock/stub)
创建一个假的对象和其假方法。
下面是一个愚蠢的expect()例子,只用与说明double的定义。
it "can create doubles" do
twin = double(first_name: "Paul", weight: 100)
expect(twin.first_name).to eq("Paul")
end
double(参数1,参数2)
#参数1 是一个可选的string,作为名字,参数2是key/value pairs 代表传送给double的信息。上一个double没有名字。
allow and expect方法:
twin = double(first_name: "Paul", weight: 100) 等同于