Over in a GitHub issue, @vladimirtcats asked this:
I have created provider:
Hanami.app.register_provider :serializers do prepare do require "oj" require "alba" end start do Alba.backend = :oj end end
But I can’t use Alba and oj in specs
only after requiring this code in
spec/spec_helper.rb
require "oj" require "alba" # or Hanami.boot
it works
How can I do it correctly?
Firstly, thanks for trying out different things with Hanami! This is a good question, so I thought I’d bring an answer over here into the forum for better visibility
So Hanami’s default RSpec setup does not ever fully boot the app: Hanami.boot
or require "hanami/boot"
do not feature anywhere in spec/spec_helper.rb
or the other files it loads.
This is by design — by avoiding a full app boot, it helps your individual specs run as fast as possible, because they only load the components from the app that they actually need.
However, in the case of a provider like yours, or basically any bit of code that won’t be automatically loaded as part of your tests interacting with one of your classes or with the app in general, you’ll need to do the work to start that provider explicitly.
In your case, this could be as simple as adding something like this to your spec_helper.rb
:
Hanami.app.start :serializers
This would ensure that the oj and alba gems are loaded and configured appropriately before any of your tests run.
Another approach could be to start that provider the first time you encounter an example with a specific tag, e.g.
RSpec.configure do |config|
config.before :each, :serializer do
Hanami.app.start :serializers
end
end
Then you’d just need to remember to add the tag to your examples, e.g. RSpec.describe "my serializer", :serializer do ... end
.
Or you could do even fancier things on top of this:
RSpec.configure do |config|
config.define_derived_metadata(file_path: %r{/serializers/}) do |metadata|
metadata[:serializer] = true
end
end
This would automatically add the :serializer
metadata to any file inside a /serializers/
dir within your tests, so you don’t need to remember to add it yourself.
So you have a few options, you can pick the one which feels best to you
One more idea: because your provider is actually not very complex, the other way you can ensure that that code is always loaded appropriately could be to leverage a serializer superclass. If all your app’s serializer’s inherited from a common superclass, then you could add the three lines from your provider to the file defining that superclass:
require "oj"
require "alba"
Alba.backend = :oj
module MyApp
class BaseSerializer
# ^ then your serializers inherit from that
end
end
This matches the pattern we use for base action, view, etc. classes within Hanami apps. Those base classes serve as a place where any critical config/setup code can exist, ensuring it is always loaded before any subclasses are defined.
I hope this helps!