file-uploadrspecmockingmerb

Testing authenticated file uploads in merb


This is something that has been driving me mad over the past few days. I have an action which allows authenticated users to upload assets to the site. I know that the controller action is correct as I can run through the process manually however I want to test it using rspec.

I have to use the request helper so I can reuse an authenticated session which is a :given for this set of tests.

it "should allow authenticated file uploads" do
    file = File.open(a_valid_file)
    mock_file = mock("file")
    mock_file.stub!(:path).and_return(file.path)

    request( resource(:assets), :method => "POST",
        :params => { :file => 
            {:tempfile => mock_file, :filename => File.basename(file.path)} }
    )
end

If I breakpoint inside the spec it all works nicely, however when I run the spec and try to access the path in the controller action through the debugger I get this:

e file[:tempfile].path
NoMethodError Exception: undefined method `path' for "#[Spec::Mocks::Mock:0x3fda2a4736c0 @name=\"file\"]":String

My guess is that the stub!(:path) is not being set for whatever mock object is making it through the request.

The question is: Am I going about the right way for testing file uploads and if not what is another way?


Solution

  • I was doing it wrong. By using request it was calling to_s on all paramaters, so my mock object was being passed as "#[Spec::Mocks::Mock:0x3fda2a4736c0 @name=\"file\"]". That will teach me to pay more attention to exception output.

    Instead I should use multipart_post and stub out the authentication calls in a block.

    it "should allow authenticated file uploads" do
        file = File.open(a_valid_file)
    
        multipart_post( resource(:assets), :method => "POST", 
                :params => { :file => file } ) do |controller|
            controller.stub!(:ensure_authenticated).and_return(true)
            controller.session.stub!(:user).and_return(User.first)
    
        )
    end