鉴于此:
假设我有以下代码:
module RedisHelper
private
def key_for(id)
[prefix, id].join('-')
end
def prefix
self.class.name.split('::').last.underscore
end
end
class X
include RedisHelper
def perform(id)
key = key_for(id)
redis.sadd(key, [:bar])
end
end
class Y
include RedisHelper
def perform(id)
key = key_for(id)
redis.set(key, :foo)
end
end
在不过度测试key_for
/ prefix
方法的情况下,最好的方法是什么?在测试类X
和Y
时,我不想重复其逻辑。
我不认为公开RedisHelper
的方法是件好事,因为它们在X
和Y
中也是公开的。
答案 0 :(得分:2)
直接回答
直接测试模块:
def test_redis_key_namespacing
dummy_class = Class.new do # this anonymous class will not pollute namespace
include RedisHelper
public :key_for
def self.name
'Dummy'
end
end
assert_equal 'Dummy-hello', dummy_class.new.key_for('hello')
end
总体建议
我建议不要使用RedisHelper
模块。尝试将“ Redis命名空间代码”逻辑保持在一起并与其他代码分开是很好的,但实际上,到处都是“ Redis命名空间代码”。
key_for
在X
和Y
中-他们必须处理每次调用redis的命名空间。同样,key_for
和prefix
都可以在任何这些类(和子类和任何其他包含的模块)中调用,即使它们是都在“ Redis名称空间”内部。
在您的应用程序中,“ Redis键命名空间”似乎是一个重要概念。它可以在多个地方被不同的无关区域重用。使其成为“事物”:
class NsRedis
key_methods = Redis.instance_methods(false).select do |m|
Redis.instance_method(m).parameters.first == [:req, :key]
end
# some metaprogramming, but it's static, much better than method_missing!
key_methods.each do |m_name|
define_method(m_name) do |key, *args|
Redis.current.public_send("#{@namespace}:#{key}", *args)
end
end
def initialize(namespace)
@namespace = namespace
end
end
# Now, anywhere you're going to need it, including tests:
class X
def initialize
@redis = NsRedis.new(self.class.name)
end
def do_something
@redis.set(:my_key, 'my_val') # "unaware" of the namespacing at usage
end
end
答案 1 :(得分:0)
在RSpec中,您可以使用shared examples:
RSpec.shared_examples "Redis namespacing helper" do
# your tests for key_for, prefix and what-have-you
end
RSpec.describe X do
it_behaves_like "Redis namespacing helper"
end
RSpec.describe Y do
it_behaves_like "Redis namespacing helper"
end
在minitest中,这可能是通过在共享测试中简单地包含模块来解决的。