require 'delegate'
class Fred < SimpleDelegator
def initialize( s )
super
end
end
puts Fred.new( [] ) == [] # ==> true
puts Fred.new( {} ) == {} # ==> true
puts Fred.new( nil ) == nil # ==> true
但
require 'test/unit'
class FredTest < Test::Unit::TestCase
def test_nilliness
assert_nil Fred.new( nil )
end
end
...返回 运行测试:
F
在0.000501s完成测试,1996.0080测试/秒,1996.0080断言/ s。
1)失败: test_nilliness:20 预计无零。
1次测试,1次断言,1次失败,0次错误,0次跳过
咦? assert_nil是否检查NilClass?在这种情况下,这将失败。
答案 0 :(得分:1)
test / unit的#assert_nil方法正在调用#nil?找出对象是否为零。问题是,Fred的祖先链中的Object定义了#nil?。由于SimpleDelegator只委托丢失方法,#nil?正在返回Fred的结果,而不是委托人。
要解决这个问题,你可以定义nil吗?并亲自转发给代理人:
def nil?
__getobj__.nil?
end
这个答案也适用于minitest。
答案 1 :(得分:0)
“嗯?断言是否检查NilClass?在这种情况下会失败。”
1.8.7在Test::Unit::Assertions
中但是对于&gt; 1.8.7,请查看MiniTest::Assertions
并查看@ WayneConrad的回答/评论,因为这是正确的。
不完全是它相互检查类,因为其他一切都失败但字符串表示是相同的。如果你查看它使用的assert_equal
来源检查以下内容:
pretty_inspect
字符串是相同的(在您的情况下是)if exp_str == act_str
Fred.new(nil).pretty_inspect.chomp #=> "nil"
nil.pretty_inspect.chomp #=> "nil"
是字符串或两个正则表达式(在您的情况下为否)if (exp.is_a?(String) && act.is_a?(String)) ||(exp.is_a?(Regexp) && act.is_a?(Regexp))
是Floats(在你的情况下没有)elsif exp.is_a?(Float) && act.is_a?(Float)
是时间(在您的情况下为否)elsif exp.is_a?(Time) && act.is_a?(Time)
是不等的类(在你的情况下是)elsif exp.class != act.class
Fred.new(nil).class #=> Fred
nil.class #=> NilClass
然后消息等于"<#{exp_str}>#{exp_comment} expected but was\n<#{act_str}>#{act_comment}"
其中exp_str
和act_str
为pretty_inspect
字符串,exp_comment
和act_comment
为对象类。从技术上讲,这条消息将会读取
"<nil>NilClass expected but was\n<nil>Fred"
然后使用===
比较它们并将其传递给assert
nil === Fred.new(nil) #=> false
这是文档