Skip to content

Make null_store the default cache store in test environment config - #33773

Merged
georgeclaghorn merged 1 commit into
rails:masterfrom
mcnelson:null_cache_store_for_test_env
Sep 2, 2018
Merged

georgeclaghorn merged 1 commit into
rails:masterfrom
mcnelson:null_cache_store_for_test_env

Conversation

@mcnelson

@mcnelson mcnelson commented Sep 1, 2018

Copy link
Copy Markdown
Contributor

Summary

It's surprising to me that by default, low-level caching is functional in the test environment. This simply adds config.cache_store = :null_store in config/environments/test.rb.

The existing defaults in test.rb as well as the Rails Guides kinda have you believe the null_store is the default.

Really was on the fence about opening this as it may not be a substantial enough change to warrant dev resources. But since Rails has such a great reputation of providing sane defaults, I felt like this would be worth it.

Other Information

I perused the tests and wasn't sure where best to add anything. railties/test/application/generators_test.rb?

Appropriate to update CHANGELOG?

@rails-bot

Copy link
Copy Markdown

Thanks for the pull request, and welcome! The Rails team is excited to review your changes, and you should hear from @eileencodes (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

This repository is being automatically checked for code quality issues using Code Climate. You can see results for this analysis in the PR status below. Newly introduced issues should be fixed before a Pull Request is considered ready to review.

Please see the contribution instructions for more information.

@georgeclaghorn

Copy link
Copy Markdown
Contributor

I’ve stubbed my toe on this before. 👍

Nothing changes for existing apps unless they opt into the new default via rails app:update, so I don’t think a changelog entry is necessary. Thanks!

@georgeclaghorn
georgeclaghorn merged commit 53eea40 into rails:master Sep 2, 2018
@eileencodes

Copy link
Copy Markdown
Member

@mcnelson can you open a new PR with a changelog? It's important to mention this change in behavior.

@mcnelson

mcnelson commented Sep 2, 2018

Copy link
Copy Markdown
Contributor Author

Done: #33779

bogdanvlviv added a commit to bogdanvlviv/rails that referenced this pull request Sep 3, 2018
@Kerrick

Kerrick commented Nov 15, 2025

Copy link
Copy Markdown
Contributor

This default means rate_limit doesn't work in test environments by default, which was a surprising foot gun when I tried covering the Rails 8 authentication generator's files. It could be worth mentioning in the rate_limit docs that in order to test rate limiting, you'll need to change config.cache_store = :null_store to config.cache_store = :memory_store in config/environments/test.rb. It would go great in or after this paragraph:

Rate limiting relies on a backing ActiveSupport::Cache store and defaults to config.action_controller.cache_store, which itself defaults to the global config.cache_store. If you don’t want to store rate limits in the same datastore as your general caches, you can pass a custom store in the store parameter.

@zzak

zzak commented Nov 16, 2025

Copy link
Copy Markdown
Member

@Kerrick Would you mind sending a PR?

Kerrick added a commit to Kerrick/rails that referenced this pull request Nov 17, 2025
zzak pushed a commit to Kerrick/rails that referenced this pull request Dec 27, 2025
zzak pushed a commit to Kerrick/rails that referenced this pull request Dec 27, 2025
@callmesangio

callmesangio commented Dec 29, 2025 •

Copy link
Copy Markdown
Contributor

I recently had a hard time testing rate limits on controllers.

Ideally, I think the best would be to be able to swap caching backend on-demand. That is, rather than globally switch to config.cache_store = :memory_store in config/environments/test.rb, leave it to :null_store and then explicitly opt-in to :memory_store around a block in specific test methods.

It seems to me that AS::Cache::NullStore could potentially be used exactly like this, since it prepends AS::Cache::Strategy::LocalCache, which provides a with_local_cache method that allows enabling a temporary in-memory cache. Unfortunately, the increment method (the one used for rate limiting purposes) bypasses the local cache (I can't tell exactly why), so this is not viable for testing rate limits.

FWIW, I've come up with a custom solution:

# config/environments/test.rb
require "cache/store_proxy"

Rails.application.configure do
  # ...
  config.cache_store = StoreProxy.new
  # ...
end

# lib/cache/store_proxy.rb
class StoreProxy
  def initialize(...)
    @store = ActiveSupport::Cache::NullStore.new(...)
  end

  def self.supports_cache_versioning?
    true
  end

  def with_memory_store(...)
    was_store = @store
    @store = ActiveSupport::Cache::MemoryStore.new(...)
    yield
  ensure
    @store = was_store
  end

  def method_missing(name, ...)
    @store.send(name, ...)
  end
end

Then, in a test:

test "create is rate limited" do
  params = { email_address: "foo@example.com", password: "wrong" }

  Rails.cache.with_memory_store do
    10.times do
      post(session_path, params:)
      assert_response :redirect
    end

    post(session_path, params:)

    assert_response 429
  end
end

Nothing too hard to implement, really, but I think it would be nice if Rails would provide a more fine-grained solution for controlling caching in rate limit tests.

Let me know if you want to talk about this further.

drymar pushed a commit to drymar/rails that referenced this pull request Jan 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants