【问题标题】:Rails RSpec Mocking Date.today.wday in Rake TaskRails RSpec 在 Rake 任务中模拟 Date.today.wday
【发布时间】:2014-10-25 00:50:38
【问题描述】:

我正在尝试在 rspec 的 rake 任务中模拟 Date.today.wday。

Gem 版本:RSpec 2.14.8 --- Rails 4.1.1 --- ruby​​ 2.0.0

这是我的测试的简化伪造版本,基本上说明了我正在尝试做的事情:

describe "scheduler" do
  describe ":thursday_invitations" do
    let(:run_issue_invites) do
      Rake::Task[:thursday_invitations].reenable
      Rake.application.invoke_task :thursday_invitations
    end

    before do
      Rake.application.rake_require 'tasks/scheduler'
      Rake::Task.define_task(:environment)
      Date.today.should_receive(:wday).and_return(4) ###MY NEMESIS CODE LINE
    end

    context "on thursday" do
      it "issues invitations" do
        expect(Date.today.wday).to eq(4) ###THE VERIFICATION TEST THAT KEEPS FAILING
        run_issue_invites
        expect(<other_stuff_to_test>).to <return_properly>
      end
    end
  end
end

所以,真正的关键是模拟 Date.today.wday。因为我希望能够在一周中的任何一天运行我的规范,所以我需要模拟/存根此方法以始终返回“4”(Rails 中星期四的天数)。因此,我最初设置我的测试以首先验证它正在接收“4”(测试中的断言)。如果今天是星期五(现在是星期五)并且我运行测试,它会失败说它期望“4”但得到“5”。也就是说,当我收到方法时,它没有返回我想要的值。我试过用类似的无效结果存根。通常,嘲笑是轻而易举的事,但似乎挂断的是.wday,它在Date.today 上运行。

因为这是一个 rake 任务(我对模拟不太熟悉),所以我可能需要进一步指定一些内容,但我无法深入了解它...

如果您需要任何其他澄清信息,请告诉我。

【问题讨论】:

    标签: ruby-on-rails rspec rake


    【解决方案1】:

    我认为您没有看到预期行为的原因是您正在模拟的对象与被测对象不同。

    在 Rails 4+ 环境中,这是我在 rails 控制台上看到的:

    [1]> Date.today.object_id
    70104549170200
    [2]> Date.today.object_id
    70104552970360
    

    object_id 在随后对Date.today 的调用中不同的事实意味着每次调用都返回一个新对象。所以Date.today.should_receive(:wday).and_return(4) 是在对一个永远不会再次使用的对象设定期望。

    您需要重写规范以确保Date.today 每次都返回相同的对象。这是一种解决方案,为了清楚起见,省略了示例的其他部分:

    let!(:today) { Date.today }
    
    before do
      Date.stub(:today).and_return(today)
      today.should_receive(:wday).and_return(4)
    end
    
    it "issues invitations" do
      expect(Date.today.wday).to eq(4)
    end
    

    【讨论】:

    • 太棒了——谢谢!在搜索和阅读中,我找不到一个明确的例子来说明如何/为什么以这种方式存根链式方法,但你的更广泛的解释很棒。解决问题真是太棒了,但我更兴奋地更好地了解了存根的概念!你摇滚。
    • 是的,您可能可以使用存根链来替代我提出的解决方案。我不经常使用这些,但它可能看起来像:Date.stub_chain(:today, :wday).and_return(4)。任何适合你的东西。
    • 请注意,对于当前的 Rspec 3.10 版,预期的存根方式是通过allow() 例如:allow(Date).to receive(:today) { Date.parse('2021-01-06') } 参见:relishapp.com/rspec/rspec-mocks/v/3-10/docs/basics/…
    猜你喜欢
    • 1970-01-01
    • 2011-10-07
    • 2015-12-29
    • 2011-10-17
    • 2016-08-05
    • 1970-01-01
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多