仅可修改类文件时如何验证RSpec自定义be_a_phone匹配器
RSpec
be_a_phone 匹配器实现问题解答 核心疑问解答
你不需要在spec文件中定义自定义匹配器,甚至根本不需要手动调用RSpec::Matchers.define定义be_a_phone:
RSpec 内置动态谓词匹配器语法糖,对于
be_a_phone这类匹配规则,RSpec会自动调用被测试对象的phone?实例方法,只要方法返回真值/假值就能直接完成校验,完全不需要额外定义匹配器。
如果你确实想在类文件内定义自定义匹配器也可以实现,但对于当前场景属于多余操作。
现有代码的问题
你当前编写的Key类存在几个逻辑错误,无法通过测试:
- 缺少RSpec动态匹配依赖的
phone?实例方法 define_type方法分支逻辑错误:if块内提前return,非手机号的分支永远不会执行- 无效值场景下直接修改原始key值为
"invalid"属于多余逻辑,题目只要求识别key类型,不需要篡改原始输入 - 手机号匹配逻辑冗余,不需要用
scan取结果再做对比,直接用正则的match?方法即可返回布尔判断结果
可直接通过测试的实现代码
# frozen_string_literal: true class Key attr_reader :key, :type # 符合E.164通用手机号规则,完全适配给出的测试用例 PHONE_REGEX = /^\+[1-9]\d{1,14}$/ def initialize(key) @key = key.to_s @type = '' define_type end # RSpec be_a_phone 匹配器自动调用的谓词方法 def phone? @type == 'phone' end private def set_type(new_type) @type = new_type end def define_type PHONE_REGEX.match?(@key) ? set_type("phone") : set_type("other") end end
代码说明
- 正则规则以
+开头,第一位数字为非0值,后续总数字长度不超过15位,完全符合通用手机号格式规则:- 有效测试用例
+55861107350可正常匹配 - 无
+前缀的55861107350、邮箱格式jake@gmail、UUID格式字符串均无法匹配
- 有效测试用例
- 新增的
phone?方法直接判断实例类型标识,RSpec的be_a_phone匹配器会自动调用该方法完成校验,不需要修改任何spec文件 - 修复了原有分支逻辑错误,移除了多余的打印、篡改原始key的逻辑,将内部工具方法设为private保证封装性
- 正则定义为类常量,后续调整规则时不需要修改业务逻辑代码
内容的提问来源于stack exchange,提问作者Lemon_prog
相关产品推荐
相关产品推荐

