RSpec基本语法小结

笔记

Posted by Jingming on December 10, 2020

https://xdite.gitbooks.io/rspec-101/content/contents/rspec-intro/
https://stackoverflow.com/questions/28006913/rspec-allow-expect-vs-just-expect-and-return
https://www.rubyguides.com/2018/10/rspec-mocks/

RSpec是Ruby的单元测试框架,包括三个Gems,RSpec-Core负责组织测试结构;RSpec-expections提供matcher和assertion;
rspec-mocks提供模拟对象功能。

Rspec-rails gem是配合Ruby rails使用的gem。

gem install rspec 安装rspec

一、Mock和Stub的区别

Mock作用是制作mock对象替换原来对象(例如未开发的复杂对象),这样原来对象的真实方法不会被调用到。

例如:Expect(mock).to receiver(:method_name).with(“params”)

作用是测试运行过程中,期待mock对象会先被传入要测的对象A中替换掉它,然后存在调用A. method_name(“params”),其中的mock. method_name(“params”)被调用到一次。

注意的是,A中一定要有method_name的定义,且该定义要调用mock对象的method_name并传入“params”作为参数。

Stub是模拟一个可以返回值的方法,和mock一样把方法调用过程屏蔽掉,但区别是Stub注重返回,Mock注重调用过程正确。Mock出来的一定后面得调用到否则报错,而stub不一定需要。

spy对象不需要类真正定义该方法。

二、doubles与instance_double

使用double的变种instance_double的好处是,可以配合allow (对应stub) 和 expect (对应mock)使用。

例如:

 expect(class_name).to receive(:method_name).with("params").and_return(result)

作用是根据class_name类型创建mock对象M,对mock对象对method_name方法(class里面一定有该方法)进行模拟,并期待在将来 M被调用,且一定传入了”params”,此时一定给他返回结果result。

 allow(class_name).to receive(:method_name).with("params").and_return(result)

作用是根据class_name类型创建Stub对象S,对mock对象对method_name方法(class里面不需要有该方法)进行模拟,不期待在将来 M被一定传入了”params”调用,但是只要被调用,那么返回哨兵结果result。

class_double与instance_double区别在对类方法模拟。

三、测试结构

  • describe描述一组相关的测试,同义词context,例如测试一个Card类。#一般加在实例名前面表示测试实例方法,.一般加在类名前面表示测试类。 特色之处在于:describe不一定是平行的,而是可以形成树状结构,也就是对测试情况进行”文件夹”结构的组织。例如it中出现了很多的if,when关键字, 那么完全可以把情况抽象到describe,例如 describe ‘with even number’ do end。
  • it 表示一个example测试
  • before 在describe里面定义一个before模块,在每个方法执前都会执行 执行顺序: before suite before(:all)或者before(:context) // 在describle组所有测试example开始前执行 before(:each)或者before(:example) // 在每个测试example之前执行 after each或者after(:example) after all或者after(:context) after suite

注意的是,describe外部的before(:example)对describe内部的example也有影响,但是这个影响发生在 describe内部的before(:context)之后和内部的before(:example)之前。

  • let 定义在describe里面,创建一个公用的变量,供所有的测试例子共享,与before的区别在于let是懒加载的 如果希望保证在测试前运行加载,那么需要使用let!也就是加上感叹号(bag)。 。
  • subject:spec文件自带的hash类型,但是在每个it执行的时候,都会获取一个新的subject对象。 subject对象可以被重写掉,subject还可以拥有别名(在第一个型参中配置)。subject对象的意思是测试的主题。
  • Rspec.describe 类名的好处是,之后可以使用describe_class.new来创建对象,这样创建对象时候省去了指定类名。
  • is_expected来隐式调用subject,等价于expect(subject)。这也是subject的好处。