如何解决模拟红宝石核心课程的正确方法
我想知道此解决方案是否被红宝石中的嘲笑对象社区认可。如果没有,请说明原因,以及如何改善代码设计或测试。
考虑我有以下代码。
lib/config_loader.rb
class ConfigLoader
HOME_DIR = '~/my/home_dir'.freeze
...
def load(path)
path = File.expand_path(path)
if File.exist?(path)
File.read(path)
else
File.read(HOME_DIR)
end
end
end
在测试时,我实际上不希望在变量中定义的path
下创建任何东西,所以我只想模拟这种行为
spec/lib/config_loader_spec.rb
RSpec.describe ConfigLoader do
describe '.load' do
subject { described.class.new.load(path) }
let(:path) { 'path/that/should/exist' }
context 'when path' do
before do
allow(File).to receive(:exist?).with(path).and_return(true)
allow(File).to receive(:read).with(path).and_return('my content')
end
it { expect { subject }.to_not raise_error { Errno::ENOENT }
end
end
end
也许我应该做class_double
类的一部分File
。我不确定我提供的方式,所以我需要一些信息以常见/最佳实践方式进行操作
解决方法
测试驱动/行为驱动的开发/设计的基本原则之一是不要嘲笑您不拥有的东西(该书{ {3}})。
您的示例违反了这一宗旨:您不拥有File
,因此您不应嘲笑它。
相反,您可以做的是创建与文件系统交互的您自己的抽象,该抽象仅具有您实际需要的功能。然后,您可以创建此抽象的两种实现:一种使用Ruby的File
类,另一种不执行任何操作。如果想花哨的话,甚至可以创建一个模拟内存中文件系统的文件。
当然,您现在已经解决了这个问题:您现在在文件抽象实现中有了 unested 代码。但是,理想情况下,此代码“几乎”是微不足道的。显然,您仍然可以为文件抽象实现进行集成测试,也可以为ConfigLoader
使用真实实现而不是模拟或仿真的集成测试。
如果您有兴趣的话,可以继续阅读以下内容:
- Growing Object-Oriented Software,Guided by Tests by Steve Freeman and Nat Pryce
- That's Not Yours,Eric Smith (8th Light)
- Don't mock what you don't own,Testdouble.com
- TDD: Only mock types you own,Mark Needham (Neo4J)
- Don't Mock What You Don't Own,Maksim Ivanov
- Don't Mock What You Don't Own,Matt's Codecave
- Don’t mock what you don’t own: a real world scenario,Giovanni Pinto
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。