Ruby 在测试类和测试类之间共享状态
我正在用RSpec做实验。 因为我不喜欢mock,所以我想使用Ruby 在测试类和测试类之间共享状态,ruby,rspec,Ruby,Rspec,我正在用RSpec做实验。 因为我不喜欢mock,所以我想使用StringIO对象模拟控制台打印 因此,我想测试Logger类是否将Welcome写入控制台。为此,我的想法是从spec文件中重写Logger中使用的put方法,以便在其他地方使用Logger时不会发生任何实际更改 下面是一些代码: describe Logger do Logger.class_eval do def puts(*args) ???.puts(*args)
StringIO
对象模拟控制台打印
因此,我想测试Logger
类是否将Welcome
写入控制台。为此,我的想法是从spec文件中重写Logger
中使用的put
方法,以便在其他地方使用Logger
时不会发生任何实际更改
下面是一些代码:
describe Logger do
Logger.class_eval do
def puts(*args)
???.puts(*args)
end
end
it 'says "Welcome"' do
end
通过这种方式,我需要在Logger
类和测试类之间共享一些StringIO
对象(现在问号所在的位置)
我发现在RSpec测试中,self
是类的一个实例。我最初的想法是这样做:
Class.class_eval do
attr_accessor :my_io
@my_io = StringIO.new
end
然后将?
替换为Class.my\u io
当我这么做的时候,无数的钟声在我脑海中响起,告诉我这不是一个干净的方法
我能做什么
附言:我还是不明白:
a = StringIO.new
a.print('a')
a.string # => "a"
a.read # => "" ??? WHY???
a.readlines # => [] ???
仍然:StringIO.new('hello')。readlines#=>[“hello”]
为了响应您最后的问题,StringIO
模拟文件行为。写入/打印时,输入光标位于上次写入的内容之后。如果您写了一些东西并想读回,您需要根据
相反,StringIO.new('hello')
将hello
建立为字符串的初始内容,同时保留在0的位置。无论如何,string
方法只返回内容,与位置无关。不清楚为什么RSpec中的test double机制存在问题
也就是说,您共享方法的方法是有效的,尽管:
- 事实上,
self
是RSpec的descripe
中的一个匿名类,这一点并不重要
- 您可以定义自己的类和关联的类方法,并将其“共享”,而不是使用
类的实例方法,如下所示:
福班
def自调节杆(arg)
puts(arg)
结束
结束
请描述“共享stringio”是什么
Foo.class\u eval do
定义自置位(*args)
MyStringIO.my_io.print(*args)
结束
结束
MyStringIO类
@my_io=StringIO.new
def self.my_io@我的爱;结束
结束
它“说”欢迎“做什么
富吧(“欢迎”)
expect(MyStringIO.my_io.string).to eql“Welcome”
结束
结束
记录器
已经允许在上指定输出设备,因此您可以轻松地直接传入您的StringIO
,而无需重新定义任何内容:
require 'logger'
describe Logger do
let(:my_io) { StringIO.new }
let(:log) { Logger.new(my_io) }
it 'says welcome' do
log.error('Welcome')
expect(my_io.string).to include('ERROR -- : Welcome')
end
end
正如其他海报所提到的,不清楚您是打算测试Logger
还是使用它的一些代码。在后者的情况下,将记录器考虑到客户端代码中。
的答案还显示了在客户端之间共享通用记录器的几种方法。这非常适合:)。非常感谢。很抱歉,我不知道Logger
是一个Ruby模块:)。我的意思是表示要测试的泛型类(不幸的是,我也将其命名为Logger
)。所以重点是测试一个泛型类。PS:无论如何,当您创建@my_io
并在class_eval
中引用它时,@my_io
不是引用了记录器
类变量吗?(假设self
指向Logger
)。当然,你是对的。对不起,那件事。我的编辑窗口和我正在测试的内容之间存在断开连接。;-)无论如何,我更新了答案,并考虑到您不打算引用Ruby的日志。有一个误解,请参阅对Peter答案的评论。啊,我明白了。实际上,我建议使用与stdlib记录器相同的设计:允许注入混凝土输出设备(在施工期间或通过设置器)。这使得测试非常容易(只需传入一个StringIO
),而且将Logger
与实际的日志记录目标分离-所有这些都不需要太多麻烦,也没有黑客攻击。