Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing Middleware with Rspec

Tags:

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 
like image 439
User314159 Avatar asked Jul 06 '13 19:07

User314159


People also ask

Is RSpec used for unit testing?

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.

What is RSpec testing?

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.

What is Rack middleware?

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.

What is RSpec DSL?

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.


1 Answers

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 
like image 56
Ritchie Avatar answered Sep 24 '22 16:09

Ritchie