有两个类,userdevice(在notificationadapter中,我使用aws sdk,而userdevice使用notificationadapter实例。
关节点在下面,
protected def notificationAdapter
@notificationAdapter ||= NotificationAdapter.new(self)
end
在userdevice测试中,我想模拟临时的notificationadapter以替换原始的notificationadapter,并且只在测试中使用这个模拟。
但我不知道该怎么做,因为这是我第一次使用mock-in测试。
我认为这需要两个步骤,
在测试代码中创建临时NotificationAdapter类(NorificationAdapterMock)。
NotificationAdapterMock = MiniTest::Mock.new mock.expect :setEndpoint, 'arn:testEndpoint' mock.expect :subscribeToAnnouncement, true
将userdevice的notificationadapter方法更改为下面的,
protected def notificationAdapter @notificationAdapter ||= NotificationAdapterMock end
但我不知道这是对还是错。我该怎么办?
最佳答案
你需要mock
你的NotificationAdapter
,因此它不会启动网络,而是做一些安全和简单的事情
还要确保适配器连接正确
侧注:请按照ruby style guidelines,方法名和变量应使用snake case而不是camel case。
所以,我们可以这样写:
require 'minitest/autorun'
class NotificationAdapter
def initialize(device)
@device = device
end
def notify
# some scary implementation, that we don't want to use in test
raise 'Boo boo!'
end
end
class UserDevice
def notification_adapter
@notification_adapter ||= NotificationAdapter.new(self)
end
def notify
notification_adapter.notify
end
end
describe UserDevice do
it 'should use NotificationAdapter for notifications' do
device = UserDevice.new
# create mock adapter, that says 'ohai!' on notify
mock_adapter = MiniTest::Mock.new
mock_adapter.expect :notify, 'ohai!'
# connect our mock, so next NoficationAdapter.new call will return our mock
# and not usual implementation
NotificationAdapter.stub :new, mock_adapter do
device.notify.must_equal 'ohai!'
end
end
end
更多信息可以在minitest的mocks和stubs文档中找到。
但我们不要停在这里!我建议您将业务逻辑从
ActiveRecord
模型转移到单独的服务类。这将产生以下良好效果:你的模特变瘦了
特性很好地封装在它自己的类中,现在遵循单一责任原则
您的测试变得非常快,因为您不需要加载rails,而是可以模拟您的模型。
这里是:
require 'minitest/autorun'
# same adapter as above
class NotificationAdapter
def initialize(device)
@device = device
end
def notify
raise 'Boo boo!'
end
end
class UserDevice
# the logic has been moved out
end
class NotifiesUser
def self.notify(device)
adapter = NotificationAdapter.new(device)
adapter.notify
end
end
describe NotifiesUser do
it 'should use NotificationAdapter for notifications' do
# Let's mock our device since we don't need it in our test
device = MiniTest::Mock.new
# create mock adapter, that says 'ohai!' on notify
mock_adapter = MiniTest::Mock.new
mock_adapter.expect :notify, 'ohai!'
# connect our mock, so next NoficationAdapter.new call will return our mock
# and not usual implementation
NotificationAdapter.stub :new, mock_adapter do
NotifiesUser.notify(device).must_equal 'ohai!'
end
end
end
祝您有个美好的一天!
另外,如果你想了解更多关于独立测试、模拟技术和一般的“快速Rails测试”运动的知识,我强烈推荐你使用Gary Bernhardt的destroyallsoftware.com截图。这是有报酬的东西,但很值得。