前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【每周一库】- mockall 对象模拟库(第二部分)

【每周一库】- mockall 对象模拟库(第二部分)

作者头像
MikeLoveRust
发布2020-05-29 15:56:10
3320
发布2020-05-29 15:56:10
举报
文章被收录于专栏:Rust语言学习交流

上次为大家介绍了mockall的部分核心功能,这次将继续介绍这个库提供的其他一些在单元测试时常用的功能。

mockall (第二部分)

一个强大的Rust对象模拟库

Mockall 可以模拟几乎所有的结构体和特征。模拟出的对象可在单元测试中作为替代实际的依赖对象使用。

规定调用次数

默认情况下,每个“期望”允许被调用无限次。但是Mockall允许开发者自己定义某个“期望”会被调用的次数(固定次数或某个范围)来测试代码的行为是否正确。

代码语言:javascript
复制
#[automock]trait Foo {    fn foo(&self, x: u32);}
let mut mock = MockFoo::new();mock.expect_foo()    .times(1)    .return_const(());
mock.foo(0);    // Okmock.foo(1);    // Panics!

运行次序序列

默认情况下,“期待”的调用与运行不会要求按规定次序执行。但是在Mockall中开发者可以通过Sequence规定次序。任何“期待”都可以被添加进同一次序序列中,并且没有对象限制。

代码语言:javascript
复制
#[automock]trait Foo {    fn foo(&self);}
let mut seq = Sequence::new();
let mut mock1 = MockFoo::new();mock1.expect_foo()    .times(1)    .in_sequence(&mut seq)    .returning(|| ());
let mut mock2 = MockFoo::new();mock2.expect_foo()    .times(1)    .in_sequence(&mut seq)    .returning(|| ());
mock2.foo();    // Panics!  mock1.foo 应该先被调用

检查点

某些情况下,在测试运行中,有必要验证全部“期待”是否被满足,丢弃已有的、或添加新的“期待,检查点可用来达成此目的。每一个模拟对象都会有一个checkpoint方法。当其被调用,Mockall会立即验证此方法的所有“期待”。任何没有被满足的“期待”都会被当做panic处理。之后,这些“期待”会被清除以便加入新的“期待”以继续进行测试。

代码语言:javascript
复制
#[automock]trait Foo {    fn foo(&self);}
let mut mock = MockFoo::new();mock.expect_foo()    .times(2)    .returning(|| ());
mock.foo();mock.checkpoint();  // Panics!  foo 还未被调用2次

代码语言:javascript
复制
#[automock]trait Foo {    fn foo(&self);}
let mut mock = MockFoo::new();mock.expect_foo()    .times(1)    .returning(|| ());
mock.foo();mock.checkpoint();mock.foo();         // Panics!  此期待被清除

通过引用传递的参数

Mockall也可以模拟使用通过引用传递参数的方法。但是需要注意的是:匹配器Predicate将通过值处理参数,不通过引用

代码语言:javascript
复制
#[automock]trait Foo {    fn foo(&self, x: &u32) -> u32;}
let mut mock = MockFoo::new();let e = mock.expect_foo()    // Note that x is a &u32, not a &&u32    .withf(|x: &u32| *x == 5)    .returning(|x: &u32| *x + 1);
assert_eq!(6, mock.foo(&5));

引用返回值

Mockall可以使用引用返回值,但是有一个限制:返回引用的证明周期必须与模拟对象的生命周期一致,或者使用'static

Mockall会为返回引用的方法创建不同的“期待”类型。它们的API除了设置返回值的方式不同外与普通的“期待”一样。

返回'static引用的方法与任何其他返回'static值的方法并无差异。

代码语言:javascript
复制
struct Thing(u32);
#[automock]trait Container {    fn get(&self, i: u32) -> &'static Thing;}
const THING: Thing = Thing(42);let mut mock = MockContainer::new();mock.expect_get()    .return_const(&THING);
assert_eq!(42, mock.get(0).0);

参数中有&self的方法示例:

代码语言:javascript
复制
struct Thing(u32);
#[automock]trait Container {    fn get(&self, i: u32) -> &Thing;}
let thing = Thing(42);let mut mock = MockContainer::new();mock.expect_get()    .return_const(thing);
assert_eq!(42, mock.get(0).0);

参数中用&mut self的方法示例:

代码语言:javascript
复制
struct Thing(u32);
#[automock]trait Container {    fn get_mut(&mut self, i: u32) -> &mut Thing;}
let thing = Thing(42);let mut mock = MockContainer::new();mock.expect_get_mut()    .return_var(thing);
mock.get_mut(0).0 = 43;assert_eq!(43, mock.get_mut(0).0);

作为Deref常见目标的超大类型比较特殊。Mockall会自动使用类型所属的形式。目前支持CStr, OsStr, Path, str。使用这一特性是完全自动的。

代码语言:javascript
复制
#[automock]trait Foo {    fn name(&self) -> &str;}
let mut mock = MockFoo::new();mock.expect_name().return_const("abcd".to_owned());assert_eq!("abcd", mock.name());
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust语言学习交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • mockall (第二部分)
    • 规定调用次数
      • 运行次序序列
        • 检查点
          • 通过引用传递的参数
            • 引用返回值
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档