I've written some Rack-Middleware and now I'm trying to test it with Rspec. But all Rack-Middleware is instantiated with an 'app' argument, that represents the Rails app itself. How do you guys mock this up in Rspec?
For example,
describe MyMiddleWare do let(:app) { # How do I mock a Rails app object here? } subject { MyMiddleWare.new(app: app) } it 'should blah blah blah' do # a bunch of tests go here end end
RSpec is a unit test framework for the Ruby programming language. RSpec is different than traditional xUnit frameworks like JUnit because RSpec is a Behavior driven development tool. What this means is that, tests written in RSpec focus on the "behavior" of an application being tested.
RSpec is a testing tool for Ruby, created for behavior-driven development (BDD). It is the most frequently used testing library for Ruby in production applications. Even though it has a very rich and powerful DSL (domain-specific language), at its core it is a simple tool which you can start using rather quickly.
Rack middleware is a way to filter a request and response coming into your application. A middleware component sits between the client and the server, processing inbound requests and outbound responses, but it's more than interface that can be used to talk to web server.
RSpec is a computer domain-specific language (DSL) (particular application domain) testing tool written in the programming language Ruby to test Ruby code. It is a behavior-driven development (BDD) framework which is extensively used in production applications.
You just need the world's simplest Rack app:
let(:app) { lambda {|env| [200, {'Content-Type' => 'text/plain'}, ['OK']]} }
Also, your middleware's constructor should receive an app as its first parameter not a hash so it should read:
subject { MyMiddleWare.new(app) }
In all likelihood, though, your test is going to need to determine what effect the middleware has had on the request. So you might write a slightly more sophisticated rack app to spy on your middleware.
class MockRackApp attr_reader :request_body def initialize @request_headers = {} end def call(env) @env = env @request_body = env['rack.input'].read [200, {'Content-Type' => 'text/plain'}, ['OK']] end def [](key) @env[key] end end
and then you'll probably want to use Rack::MockRequest to actually send the request. Something like:
describe MyMiddleWare do let(:app) { MockRackApp.new } subject { described_class.new(app) } context "when called with a POST request" do let(:request) { Rack::MockRequest.new(subject) } before(:each) do request.post("/some/path", input: post_data, 'CONTENT_TYPE' => 'text/plain') end context "with some particular data" do let(:post_data) { "String or IO post data" } it "passes the request through unchanged" do expect(app['CONTENT_TYPE']).to eq('text/plain') expect(app['CONTENT_LENGTH'].to_i).to eq(post_data.length) expect(app.request_body).to eq(post_data) end end end end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With