Mocking Classes/ methods in ruby in a functional test?

39 Views Asked by At

Background:-

I'm currently writing a functional test for a particular controller's action in order to validate its functionality by making a POST request.

Background on controller's action -

This action is responsible for creating an application and saving it.

Controller's action code -

def create_applicaiton

application_data = {
    application_name: request.POST['app_name']
    member_email: request.POST['email']
}

application = ApplicationRecord.new application_data

begin
 StepinHelper.create_issue(application)  //Problem is with this
rescue => error
 Rails.logger.error "Error occurred while creating Issue. Error: #{error}"
 return render plain: "Error occurred while creating Issue. Please try later. Error: #{error}, status: internal_Server_error
end

begin
ActiveRecord::Base.transaction do
application.save!
end
rescue => error
 Rails.logger.error "Error occurred while creating application. Error: #{error}"
 return render plain: "Error occurred while creating application. Please try later. Error: #{error}, status: internal_Server_error
end
return head :ok
end

The problem is with the line -

StepinHelper.create_issue(application)

where create_issue method instantiates a class IssueCreator which makes some network calls in order to create the Issue (Think of issue as a notifier that indicates an application is created) which fails during the POST request as its a functional test and the scope is beyond that where it cannot make network calls.

Here is the code for create_issue method present in StepinHelper class -

module StepinHelper
 def self.create_issue application
  issue_title = application.application_name
  issue = IssueCreator.new issue_title //instantiates IssueCreator class
  issue_create = issue.create       //This method creates the issue
  issue_id = issue_create["id"]    //This fetches the "issue_id" from the created issue
  application.add_issue_id issue_id  //This adds issue_id to the schema/table of ApplicationRecord 
 end
end

The model of the ApplicationRecord has a method - add_issue_id as mentioned above which adds a the value of issue_id to its schema's issue_id column.

This is the model of ApplicationRecord -

class ApplicationRecord < ActiveRecord::Base
self.table_name = "application_record"
......
......

def add_issue_id id
  self.issue_id = id
end
....
....

This is the schema of ApplicationRecord where issue_id is set to be NOT NULL

create_table "application_record", id: integer
 t.string "application_name", null: false
 t.string "member_email", null:false
 t.string "issue_id", null:false
end

This is my Functional test code I'm implementing using minitest -

class ApplicationControllerTest < ActionController::TestCase

test 'testing_create_applcication' do

StepinHelper.expects(:create_issue).once //mocking

post :create_application, params: {application_name: 'dummyName', member_email: '[email protected]'}

assert_response :ok
end
end

Main Problem:-

Trying to mock create_issue method like above. But my assertion fails with a 500 response because as I'm mocking create_issue method issue_id is not being created and stored in the application records.

Here is the error response -

Expected response to be a <200:ok> , but was a <500: Internal Server Error>
Response body: Error occurred while creating application. Error: SQLite3::ConstraintException: NOT NULL constraint failed: application_record.issue_id
Expected: 200
Actual: 500

Expectation/what I'm looking for: -

  1. To make sure issue_id is created by mocking the necessary methods
  2. To make my test case pass with a 200 response.

NOTE: I shouldn't make changes to the source code.

0

There are 0 best solutions below