I have several spec files for my Sinatra API. They test a Module MysuperBlog and a class API within that Module.
I have this in a RSpec config file :
RSpec.shared_context 'Reset class' do
after(:each) do
Object.send(:remove_const, :API)
end
end
the spec files all have these lines of code:
require 'rack/test'
require 'json'
require_relative '../../../app/main.rb'
module MysuperBlog
class API
RSpec.describe 'An author logs in to his account', type: :request do
include_context 'Reset class'
The main app file contains:
module MysuperBlog
class API < Sinatra::Base
Each spec succeeds but when I run rspec without arguments, it raises an error:
TypeError:
superclass mismatch for class API
I guess this is caused by the module and the class being defined in each file.
How should I reorder the code so both the individual tests and the global test pass without this error?
The
classkeyword in Ruby serves two purposes: to create a class and to re-open an existing class.If your class has a superclass other than
Object, it has to be given when creating the class but it can be omitted when re-opening it, e.g.: (I'm usingArrayjust for demonstration purposes, you shouldn't subclass core classes in general)Doing it the other way round raises the error you are seeing:
I assume that you load the file which is supposed to re-open an existing class before the file which is supposed to create the class and which specifies its superclass.
If so, ensure that you load the latter first (
requireit, e.g. in your spec helper) and your problem should be solved.If you don't actually want to re-open an existing class but instead attempt to re-use the same class name for different throw-away classes in your tests, you can remove the constant via
remove_constafter you're done with the class / test: (e.g. in an RSpecafterhook)This way, each
class Foocreates a new and independent class instead of re-opening the previous one.Objectis used for top-level constants. For nested constants, replaceObjectwith the module that actually holds the constant.