rspec的expect方法接收任何对象作为参数,并且返回一个rspec代理对象 叫做 ExpectationTarget。
ExpectationTarget存储了传递给expect方法的对象,他响应两个方法to和not_to (从技术上来说是三个, to_not是一个别名), to和not_to是普通的ruby方法,期望接收一个rspec matcher作为参数
rspe matcher没有什么特别的,仅仅是可以响应matchers?方法的对象, 你可以使用预定义的matchers或者自己定义
在我们的例子 expect(project.done?).to be_truthy 中, be_truthy是一个方法,rspec定义的,返回BeTruthy匹配器,和下面行为一样
expect(project.done?).to(RSpec::BuiltIn::BeTruthy.new)
ExpectationTarget现在存储两个对象 , 一个是被匹配的对象 project.done?和matchert叫做be_truthy。 当spec执行时, rspec在matcher调用 matches?使用使用这个Project.done?作为matcher的参数, 如果使用to, 这个maches?接收参数执行后,返回true就是通过测试, 如果使用not_to,检查matcher中有没有does_not_match?方法, 如果没有这个方法,就回头看maches?返回false表示测试通过
形式如be_whatever或者be_a_whatever关联了一个whatever?方法, 有一个问号标记在真实对象上,在我们前面的例子,expect(project.done?).to be_truthy 因为done?是一个断言方法,我们可以将这个例子写成, expect(project).to be_done
If the matcher is called via to , it passes if the predicate method returns a true value. If the matcher is called via not_to , it passes if the predicate method returns a false value.
if the predicate method starts with has , RSpec allows your matcher to start with have for readability (so your tests don’t look like they’ve been written by LOLCats); RSpec allows expect(actual).to have_key(:id) rather than expect(actual).to has_key(:id) .
RSpec 3 also allows you to chain multiple matchers using and and or , as in expect(actual).to include("a").and match(/.*3.*/) , or expect(actual).to eq(3).or eq(5) .