Rails expect(controller).not_to have_received(:get_from_database) 没有按预期工作

Posted

技术标签:

【中文标题】Rails expect(controller).not_to have_received(:get_from_database) 没有按预期工作【英文标题】:Rails expect(controller).not_to have_received(:get_from_database) not working as expected 【发布时间】:2021-09-23 08:17:58 【问题描述】:

我正在尝试通过检查是否正在调用访问数据库的函数来测试我的应用中的缓存。

我的控制器:

class MyApp::MyController < MyApp::BaseController
    def index
      @cache_key = "testkeydd"
      @current_time = Time.current
      @data = Rails.cache.fetch(@cache_key, expires_in: 1.hour) do
        get_from_database
      end
    end

    def get_from_database
      puts "============DATABASE HIT============"
      Data.last(20)
    end
end  

我的规格:

describe MyApp::MyController, type: :controller do
        let(:memory_store)  ActiveSupport::Cache.lookup_store(:memory_store) 

        before :each do
            allow(Rails).to receive(:cache).and_return(memory_store)
            Rails.cache.clear
            allow(controller).to receive(:get_from_database).and_call_original
        end

        describe 'GET /myroute' do

            it 'hits the database after creating a new booking' do
                get :index, format: :json #First request
                expect(controller).to have_received(:get_from_database) #Passes

                get :index, format: :json #Second request
                expect(controller).not_to have_received(:get_from_database) #Fails
            end
        end
end

当我运行规范时,函数 get_from_database 仅在第一个请求时调用,而不是在第二个请求时调用。

您是否希望测试通过。然而expect(controller).not_to have_received(:get_from_database) 失败:

   expected: 0 times with any arguments
   received: 1 time

【问题讨论】:

测试环境中是否启用了 Rails 缓存? @SampatBadhe memory_store 【参考方案1】:

期望的默认数量是一个,所以你应该可以设置一个期望并执行两个请求。

试试:

it 'hits the database after creating a new booking' do
  expect(controller).to have_received(:get_from_database)
  get :index, format: :json #First request
  get :index, format: :json #Second request
end

此外,在您的情况下,更清楚地测试返回 get_from_database 的任何内容都已缓存,因此您可以执行 expect(Rails.cache.fetch(...)).to eq(...) 之类的操作,这将涵盖没有 RSpec 间谍的情况。

【讨论】:

我认为 OP 的目的是测试数据库只被击中一次(fetch),所以最好明确地期待.once 以及更改测试用例描述hits the database at the first time ...(或2个测试用例?) @LamPhan 你是对的。我想测试数据库是否仅在我第一次调用该方法时被击中。我不明白你的意思,所以最好明确地期待.once。能举个例子吗? @StarMan relishapp.com/rspec/rspec-mocks/docs/setting-constraints/… @LamPhan 谢谢这似乎按预期工作

以上是关于Rails expect(controller).not_to have_received(:get_from_database) 没有按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

ruby Rails Controller代码示例

Rails:在哪里启用 Access-Control-Allow-Origin

在 rails create controller (Rails 6) 中渲染 new.js.erb

Rails current_page?与 controller.controller_name

如何在rails下的webrick中设置access-control-allow-origin?

Rails、Backbone、PhoneGap、CORS(Access-Control-Allow-Origin 错误不允许)