【问题标题】:How to rspec mock ruby rails logger class如何 rspec 模拟 ruby​​ rails 记录器类
【发布时间】:2012-01-05 04:41:04
【问题描述】:

您好,我正在尝试 rspec 模拟以下课程:

    class Person
      def initialize(personid)
        Rails.logger.debug "Creating person with id #{personid}"
      end
    end

使用这个:

require 'spec_helper'
  describe Person do
    describe "#initialize" do
      let(:rails_mock) { double("Rails").as_null_object }
      let(:logger_mock) { double("Rails.logger").as_null_object }

      it "logs a message" do
        rails_mock.stub(:logger).and_return(logger_mock)
        logger_mock.should_receive(:debug)
        Person.new "dummy"
      end
   end
end

并收到此消息:

RSpec::Mocks::MockExpectationError: (Double "Rails.logger").debug(any args)
预计:1 次
收到:0次

任何帮助都会很棒!

【问题讨论】:

    标签: ruby-on-rails ruby logging rspec mocking


    【解决方案1】:

    我愿意:

    Rails.stub_chain(:logger, :debug).and_return(logger_mock)
    

    不要忘记在测试结束时取消存根:

    Rails.unstub(:logger)
    

    【讨论】:

    • 这对我不起作用。我得到undefined method 'stub_chain' for Rails:Module (NoMethodError)
    【解决方案2】:

    这是使用部分双精度的更新答案:

    let(:personid) { 'dummy' }
    
    before do
      allow(Rails.logger).to receive(:debug).and_return nil
      Person.new(personid)
    end
    
    it { expect(Rails.logger).to have_received(:debug).with(a_string_matching(personid)) }
    

    无需“取消存根”任何内容,RSpec 会为您完成。

    【讨论】:

      【解决方案3】:

      存根不起作用,因为这些存根未链接到实际代码。它应该是这样的:

      require 'spec_helper'
        describe Person do
          describe "#initialize" do
            let(:logger_mock) { double("Rails.logger").as_null_object }
      
            it "logs a message" do
              Rails.stub(:logger).and_return(logger_mock)
              logger_mock.should_receive(:debug)
              Person.new "dummy"
            end
         end
      end
      

      对于 OP:如果您只想设置对日志记录的期望,则根本不需要存根整个 logger 类。你可以这样做

      Rails.logger.should_receive(:debug)
      

      奖励:如果您只想存根以便不会发生日志记录,请执行以下操作:

      Rails.logger.stub(:add){ true }
      

      【讨论】: