在对模块进行混合测试时,我无法理解错误。
假设要测试的mixin是模块A:
require 'path/b'
module A
def methodA()
puts methodB.attr1
end
end
这取决于在path / b.rb文件中定义的另一个mixin B
module B
def methodB
return someObject #that has property 'attr1'
end
end
现在,我们有一个可以对模块A进行单元测试的类
require 'path/moduleA'
class TestA
include Path::moduleA
end
describe 'test moduleA.methodA'
it 'does something'
testObject = TestA.new
testObject.methodA()
expect(....)
end
end
在运行rspec测试时出现以下错误
NameError:
undefined local variable or method `methodB' for #<TestA:0x00007f77a03db9a8>
我可以通过以下方式之一解决它:
问题
我不清楚为什么需要include才能访问中的methodB 模块A和TestA类(当在模块A中已经添加了'require'时)。
我的意图是在模块A中使用模块B的方法,但不要让模块A的用户自动访问模块B的方法。
分辨率1使A的用户可以访问B的方法
分辨率2强制A的用户(在此示例中为user->单元测试类)直接包含A的依赖项B,即使用户仅对访问A的方法感兴趣。
因此,两种分辨率都达不到我想要的效果。有办法实现吗?
我是Ruby的新手,所以可能不支持此功能。我来自Java背景,我将A和B建模为两个类,将B的实例作为A的字段,然后向A的用户公开A自己的公共方法。但是由于它们是mixins,因此我需要在红宝石。
答案 0 :(得分:1)
非常明确:require
/ require_relative
/ load
和include
/ extend
/ prepend
绝对没有任何事情可做彼此。
前三个仅运行Ruby文件。而已。那就是他们所做的一切。他们在搜索文件的方式和位置上有所不同,但是在找到文件后,除了执行文件之外,他们不执行任何其他操作。
后三个将模块添加到祖先链。 include
本质上使模块成为超类,extend
实际上与singleton_class.include
相同(即使模块成为单例类的超类),并且prepend
将模块插入到祖先链的开始,即实际上是在之前的类别。
答案 1 :(得分:0)
require
只是告诉ruby读取/加载ruby文件中的代码。在这种情况下,它将仅定义模块。但是,为了使模块内的代码包含在另一个模块或类内,您必须在模块或类内include
进行编码。所以您应该像您提到的那样:
require 'path/b'
module A
include B
def methodA()
puts methodB.attr1
end
end
由于模块A已经包括模块B,因此您不需要更改测试。但是,在这里这不是一个很好的OOP设计模式。但是希望您现在明白为什么。
答案 2 :(得分:0)
经过更多的搜索后,我使用来自以下方面的建议找到了第二个问题的答案: https://makandracards.com/makandra/977-calling-selected-methods-of-a-module-from-another-module
所以我基本上做到了:
require 'path/b'
module A
module B_RequiredMethods
include Path::B
module_function :methodB
end
def methodA
puts B_RequiredMethods.methodB.attr1
end
end
在我的情况下,可以正确命名B_RequiredMethods以表示B公开的B方法。理想情况下,我将这些方法设为B的类级别方法,但由其他团队来管理。