Ruby on rails 我应该如何使用RSpec全局地存根一个方法?
我正在开发一个Rails应用程序。我正在尝试全局地存根一个方法 我要做的是将其存根在RSpec配置中(:suite)之前的Ruby on rails 我应该如何使用RSpec全局地存根一个方法?,ruby-on-rails,ruby-on-rails-3,rspec,mocking,stubbing,Ruby On Rails,Ruby On Rails 3,Rspec,Mocking,Stubbing,我正在开发一个Rails应用程序。我正在尝试全局地存根一个方法 我要做的是将其存根在RSpec配置中(:suite)之前的块上,如下所示: RSpec.configure do |config| config.before(:suite) do allow_any_instance_of(MyModel).to receive(:my_method).and_return(false) end end 但是,启动测试失败,出现以下错误: 在'method_missing'中:
块上,如下所示:
RSpec.configure do |config|
config.before(:suite) do
allow_any_instance_of(MyModel).to receive(:my_method).and_return(false)
end
end
但是,启动测试失败,出现以下错误:
在'method_missing'中:未定义的方法'allow_any_instance_of'for#(nomethoderor)
有线索吗?我应该如何使用RSpec全局地存根一个方法
p.这可能是一个上下文/初始化问题。在(:each)
之前的config.before中执行此操作可以解决您的问题。您使用的是什么版本的RSpec?我相信RSPEC2.14中引入了allow\u任何实例。对于早期版本,您可以使用:
MyModel.any_instance.stub(:my_method).and_return(false)
不要在(:suite)
之前的中存根方法,因为存根在每个示例之后都会被清除,如中所述:
在(:each)
之前使用,而不是(:all)
不支持(:all)
之前的中的存根。原因是所有的存根
每个示例之后,mock都会被清除,所以设置的任何存根
在之前(:all)
将在碰巧运行的第一个示例中起作用
那群人,但不适合其他人
不要在(:all)
之前使用,而要在(:each)
之前使用
我想这就是为什么allow\u任何实例在before(:suite)
块中不可用,但在before(:each)
块中可用的原因
如果仍然缺少该方法,可能您将rspec mock配置为仅允许:should
语法
的任何实例,并为消息期望提供了所有新的:expect
语法
通过检查RSpec::Mocks.configuration.syntax
的值,确保启用此语法。它是rspec模拟中可用语法的数组。可用的语法是:expect
和:should
RSpec.configure do |config|
config.mock_with :rspec do |mocks|
mocks.syntax = [:expect, :should]
end
end
一旦配置正确,您应该能够使用allow\u任何的实例,我最近遇到一个案例,我需要在(:all)
或之前(:context)
块中存根某个内容,并发现这里的解决方案不适用于我的用例
上的RSpec文档表示不支持:
可以在示例组中直接定义前后挂钩
应在或在全局RSpec.configure块中运行
警告:在before(:suite)中不支持设置实例变量
警告:仅在before(:示例)中支持模拟。
注意:example和:context作用域也可用作:each和
:分别是全部。用你喜欢的
问题
我正在制作包含在unix epoch时间戳中的二进制头文件。我想编写RSpec测试来检查输出文件头的正确性,并将其与测试夹具二进制参考文件进行比较。为了创建快速测试,我需要在所有示例组块运行之前写出一次文件。为了对照引用文件检查时间戳,我需要强制Time.now()
返回一个常量值。这让我走上了尝试存根时间的道路。现在
返回我的目标值
但是,由于rspec/mocks
不支持(:all)
之前的或(:context)
之前的块中的存根,因此它不起作用。在(:each)
之前写入文件会导致其他奇怪的问题
幸运的是,我偶然发现了解决方案
解决方案
自2014年1月9日以来()RSpec现在包含了一个解决此问题的方法:
例子
require'spec\u helper'
需要“rspec/mock”
请描述“LZOP::File”do
前(:全部){
@预期的_lzop_magic=[0x89、0x4c、0x5a、0x4f、0x00、0x0d、0x0a、0x1a、0x0a]
@未压缩的\u文件\u data=“Hello World\n”*100
@文件名='lzoptest.lzo'
@test_fixture_path=File.join(File.dirname(uuu File_uuu)、“…”、“fixtures”、@filename+“.3”)
@lzop_test_fixture_file_data=file.open(@test_fixture_path,'rb')。读取
@tmp_filename=File.basename(@filename)
@tmp_file_path=file.join(“”,'tmp',@tmp_filename)
#Stub调用Time.now(),使用我们的伪mtime值,以便针对我们的测试夹具进行mtime\u low测试
#这是创建原始未压缩测试夹具文件时的mtime
@time_now=time.at(0x544abd86)
}
上下文“当给定文件名时,没有选项并写入未压缩的测试数据”
描述“输出二进制文件”是什么
前(:全部){
RSpec::Mocks.with_temporary_scope do
允许(时间)。接收(:now)。和返回(@Time\u now)
#将“时间是:{TIME.now}”
#将“时间是:{TIME.now.to_i}”
my_test_file=LZOP::file.new(@tmp_file_path)
my_test_file.write(@uncompressed_file_data)
@test_file_data=file.open(@tmp_file_path,'rb')。读取
结束
}
它“有正确的魔法位”做什么
expect(@test\u file\u data[0..8]。解包('C*')。到eq@expected\u lzop\u magic
结束
##[…剪断…](此处的其他示例块)
它“在LZO文件头中具有原始文件mtime”do
#将“time_now={@time_now}
如果@test_file_data[17..21]。解包('L>)。首先&LZOP::F_H_FILTER==0
mtime\U low\U start\U字节=25
mtime\u低端\u字节=28
mtime\u高\u开始\u字节=29
mtime\u高端\u字节=32
其他的
mtime\U low\U start\U字节=29
mtime\u低端\u字节=32
mtime\u高\u开始\u字节=33
mtime\u高端\u字节=36
结束
#放入“开始字节:{开始字节}”
#放置“结束字节:{结束字节}”
#将“mtime_low:#{@test_file_data[start_byte..end_byte].unpack('L>).first.to_s(16)}”
#将“test mtime:{@lzop_test_fixture_file_data[start_byte..end_byte]。解包('L>).f
require 'spec_helper'
require 'rspec/mocks'
describe 'LZOP::File' do
before(:all) {
@expected_lzop_magic = [ 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a ]
@uncompressed_file_data = "Hello World\n" * 100
@filename = 'lzoptest.lzo'
@test_fixture_path = File.join(File.dirname(__FILE__), '..', 'fixtures', @filename + '.3')
@lzop_test_fixture_file_data = File.open( @test_fixture_path, 'rb').read
@tmp_filename = File.basename(@filename)
@tmp_file_path = File.join( '', 'tmp', @tmp_filename)
# Stub calls to Time.now() with our fake mtime value so the mtime_low test against our test fixture works
# This is the mtime for when the original uncompressed test fixture file was created
@time_now = Time.at(0x544abd86)
}
context 'when given a filename, no options and writing uncompressed test data' do
describe 'the output binary file' do
before(:all) {
RSpec::Mocks.with_temporary_scope do
allow(Time).to receive(:now).and_return(@time_now)
# puts "TIME IS: #{Time.now}"
# puts "TIME IS: #{Time.now.to_i}"
my_test_file = LZOP::File.new( @tmp_file_path )
my_test_file.write( @uncompressed_file_data )
@test_file_data = File.open( @tmp_file_path, 'rb').read
end
}
it 'has the correct magic bits' do
expect( @test_file_data[0..8].unpack('C*') ).to eq @expected_lzop_magic
end
## [...SNIP...] (Other example blocks here)
it 'has the original file mtime in LZO file header' do
# puts "time_now= #{@time_now}"
if @test_file_data[17..21].unpack('L>').first & LZOP::F_H_FILTER == 0
mtime_low_start_byte=25
mtime_low_end_byte=28
mtime_high_start_byte=29
mtime_high_end_byte=32
else
mtime_low_start_byte=29
mtime_low_end_byte=32
mtime_high_start_byte=33
mtime_high_end_byte=36
end
# puts "start_byte: #{start_byte}"
# puts "end_byte: #{end_byte}"
# puts "mtime_low: #{@test_file_data[start_byte..end_byte].unpack('L>').first.to_s(16)}"
# puts "test mtime: #{@lzop_test_fixture_file_data[start_byte..end_byte].unpack('L>').first.to_s(16)}"
mtime_low = @test_file_data[mtime_low_start_byte..mtime_low_end_byte].unpack('L>').first
mtime_high = @test_file_data[mtime_high_start_byte..mtime_high_end_byte].unpack('L>').first
# The testing timestamp has no high bits, so this test should pass:
expect(mtime_low).to eq @time_now.to_i
expect(mtime_high).to eq 0
expect(mtime_low).to eq @lzop_test_fixture_file_data[mtime_low_start_byte..mtime_low_end_byte].unpack('L>').first
expect(mtime_high).to eq @lzop_test_fixture_file_data[mtime_high_start_byte..mtime_high_end_byte].unpack('L>').first
mtime_fixed = ( mtime_high << 16 << 16 ) | mtime_low
# puts "mtime_fixed: #{mtime_fixed}"
# puts "mtime_fixed: #{mtime_fixed.to_s(16)}"
expect(mtime_fixed).to eq @time_now.to_i
end
end
end
end
class MyModel
def my_method
false
end
end
allow_any_instance_of(Xyz).to receive(:do_this).and_return(:this_is_your_stubbed_output)