有两个类,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的mocksstubs文档中找到。
但我们不要停在这里!我建议您将业务逻辑从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截图。这是有报酬的东西,但很值得。

09-27 07:20