0

我正在开发一个使用 Ruby on Rails 的博客应用程序。我有一个名为 Essay 的模型,带有 Draper Decorator。我也在使用 MiniTest::Spec 来测试这个应用程序。每篇论文都有一个正文,该正文将作为 Markdown 存储。在 EssayDecorator 中,我有一个名为 body 的方法,它使用 RedCarpet 将 Markdown 呈现为 html。

为了测试这个方法,我写了如下代码:

describe '#body' do
  it 'returns html from the markdown' do
    essay = FactoryGirl.create(:essay)
    @decorated_essay = essay.decorate
    markdown = Minitest::Mock.new 

    @decorated_essay.stub :markdown, markdown do
      markdown.expect :render, "<p>Test</p>", [essay.body]
      @decorated_essay.send(:body)
      markdown.verify
    end
  end
end

在装饰器内部,我有两种方法:

  def body
    markdown.render(model.body).html_safe
  end

  def markdown
    Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true, :space_after_headers => true)
  end

这个测试通过了,但对我来说似乎很奇怪。我不想测试 RedCarpet 是否在做它的工作,我只想测试我调用了 render 方法。

是否有在 MiniTest 中模拟这种事情的最佳实践?我对使用 Mocks 很陌生,对使用 MiniTest 也很陌生。

提前致谢。

4

1 回答 1

0

IMO 这段代码看起来很奇怪,因为它不是在测试代码的行为,而是在测试实现。如果实现发生了变化(您将 HTML 存储在缓存中,而不是通过 Redcarpet 运行它),那么此测试将失败。这看起来对我来说太过分了。

我不想测试 RedCarpet 是否在做它的工作,我只想测试我调用了 render 方法。

这是执行。你为什么要通过降价运行身体?因为您希望从 URL 创建超链接?我会为此创建一个测试。您想确保链接具有 no-follow 属性吗?我会为此创建一个测试。为代码为什么做某事创建测试,而不是它是如何做的。

您也完全有可能在应用程序中缺少抽象。负责将纯文本格式化为 HTML 的东西。使用 Redcarpet 或 RDiscount 或任何其他认为重要的库的东西。EssayDecorator 可能不应该负责确保文本格式正确,但它可能负责告诉正确的对象应用格式。

于 2013-09-10T23:08:28.977 回答