【问题标题】:Mocha Mock Carries To Another TestMocha Mock 进行另一项测试
【发布时间】:2011-03-08 07:50:24
【问题描述】:

我一直在关注15 TDD steps to create a Rails application 指南 - 但遇到了一个我似乎无法解决的问题。对于 WordsController 的功能测试,我有如下代码:

class WordsControllerTest < ActionController::TestCase
  
  test "should get learn" do
    get 'learn'
    assert_response :success
  end

  test "learn passes a random word" do    
    some_word = Word.new
    Word.expects(:random).returns(some_word)
    get 'learn'
    assert_equal some_word, assigns('word')
  end
end

在 Word 类中,我有以下代码:

class Word < ActiveRecord::Base
  def self.random
    all = Word.find :all
    all[rand(all.size)]
  end
end

当我运行测试时,我遇到以下错误(为简洁起见而缩短):

1) Failure: unexpected invocation: Word(...).random() satisfied expectations:
- expected exactly once, already invoked once: Word(...).random()

我曾尝试更改测试顺序以及许多其他事情,但我一次又一次地收到相同的测试失败 - Word.random() 已被调用。

我正在运行 Rails 3.0 beta 4 和 Mocha 0.9.8。我一直在努力寻找解决问题的方法,但似乎找不到。我是 Ruby/Rails 的新手,所以对语言和框架不太熟悉。

提前致谢!

【问题讨论】:

    标签: ruby functional-testing ruby-mocha


    【解决方案1】:

    这些解决方案对我自己不起作用,使用 Ruby 2.2.2、Rails 4.2.2、mocha 1.1.0、shouda-context 1.2.1、factory_girl_rails 4.5.0 和其他一些与测试相关的 gem。

    在我的test_helper.rb 底部移动了这两行:

    require 'mocha/setup'
    require 'mocha/test_unit'
    

    我还删除了require 'test/unit'。看来mocha/test_unit 已经为我做到了。

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,模拟功能没有被隔离到测试中,这似乎是 Mocha 的加载顺序问题。

      我在让 Mocha 与 Rails3 一起工作时遇到了一些问题。我发现了一些关于 * 的帖子,但直到我在 agoragames.com 上找到帖子后才偶然发现解决方案

      基本上,在您项目的 Gemfile 中,Mocha 的需求应该如下所示:

      gem 'mocha', :require => false
      

      然后在test/test_helper.rb 中,为 mocha 添加 require 行:

      ...
      ...
      require File.expand_path('../../config/environment', __FILE__)
      require 'rails/test_help'
      require 'mocha'
      
      class ActiveSupport::TestCase
      ...
      ...
      

      我认为 Gemfile 中 mocha 的 require 行意味着您需要已经将 mocha 作为 gem 安装,bundler 不会为您处理它。

      【讨论】:

        【解决方案3】:

        此外,似乎 mocha_teardown 没有被 rails31 调用。设置的模拟永远不会被删除......(这个额外的黑客修复它)

          class ActiveSupport::TestCase
            def teardown
              super
              Mocha::Mockery.instance.teardown
              Mocha::Mockery.reset_instance    
            end
          end
        

        【讨论】:

          【解决方案4】:

          mocha 需要最后加载。我也为这个问题苦苦挣扎。

          #Gemfile
            group :test
              gem 'mocha', '~>0.9.8', :require => false
              ...
            end
          

          test_helper.rb
            ....
            #at the very bottom
            require 'mocha'
          

          【讨论】:

          • 正是我所需要的。我用这个把头发扯了好几个小时!谢谢! :)
          • +1,迁移到捆绑器我弄乱了 mocha 加载的顺序
          • 我使用 Sinatra 我应该在哪里包含它? spec_helper.rb?但我仍然有这个问题。
          • 作为一个来自 Java/Python 的 Ruby/Rails 新手,我在最后一个小时里一直在努力解决这个问题 - 不得不调试一段时间,直到我明白 mocha 的测试验证仅在来自模拟被调用(因为从最后的自动调用需要后期绑定),谢谢,谢谢,谢谢!
          【解决方案5】:

          您对摩卡的需求如何?你在使用捆绑器吗?听起来好像没有调用 mocha 拆解钩子?

          【讨论】:

          • 是否应该在测试之间调用拆解?
          • 如果 Mocha 已正确加载,它将对测试框架进行猴子修补以调用 Mocha::API#mocha_verifyMocha::API#mocha_teardown 即您不需要显式调用它们。我之所以问Mocha 是如何被要求的,是为了弄清楚事情是否以正确的顺序加载,以便猴子补丁正常工作。
          • 如果您在运行测试时将MOCHA_OPTIONS=debug 设置为环境变量,您将看到哪些测试框架正在成功地进行猴子补丁。如果您对此仍有疑问,请告诉我调试输出是什么,并告诉我您使用的是什么版本的 Mocha。谢谢。