Home > database >  In Ruby on Rails tests, how do I call from a ControllerTest a method defined inside a Controller
In Ruby on Rails tests, how do I call from a ControllerTest a method defined inside a Controller

Time:12-27

I have a test class called AdControllerTest, which I am using to test AdController. From AdControllerTest, I'm trying to call a method defined in AdController, but I don't think I'm doing it right and I can't find the correct way to do this.

My test code looks like so

  test "pctr to final list is correct for pctr policy" do
    # Make a CTR list
    # Make a selectedAds list
    # Check that the CTR list reorders the selectedAds appropriately
    response = AdCampaign.search query: {
                              bool: {
                                must: [
                                  { match:  { target_gender: "F" },
                                      match:  { target_country: "KR" } } ]
                                  }}
    selectedAds = Array.new(NUMBEROFADS) {Hash.new} 
    for i in 1..NUMBEROFADS do
      selectedAds[i-1] = response.results.to_a[i-1]
    end

    testCTR = [0.032521635096847835, 0.03863127908388814, 0.007986670179316374]

    finalAds = AdController.pctrToAd(selectedAds: selectedAds, pctr: testCTR)

    # Manually order selectedAds by testCTR and compare
    comparisonAds = Array.new(NUMBEROFADS) {Hash.new}
    comparisonAds[0] = selectedAds[1]
    comparisonAds[1] = selectedAds[0]
    comparisonAds[2] = selectedAds[2]

    assert_equal(finalAds, comparisonAds)

  end

And within that code I'm trying to call finalAds = AdController.pctrToAd(selectedAds: selectedAds, pctr: testCTR)

The method pctrToAd is definitely defined in AdController.

But I get an error like so:

Error:
AdControllerTest#test_pctr_to_final_list_is_correct_for_pctr_policy:
NoMethodError: undefined method `pctrToAd' for AdController:Class
    test/controllers/ad_controller_test.rb:166:in `block in <class:AdControllerTest>'

Am I not supposed to call the method inside a controller that way? If not, how am I supposed to call it?

CodePudding user response:

AdController.pctrToAd is calling a method on the AdController class. Presumably you want to call a method on an AdController object.

NoMethodError: undefined method `pctrToAd' for AdController:Class
                                               ^^^^^^^^^^^^^^^^^^

Assuming this is AdControllerTest, the controller object is available as @controller.

finalAds = @controller.pctrToAd(selectedAds: selectedAds, pctr: testCTR)

CodePudding user response:

You don't.

The only methods inside your controller that should be public are the actions of the controller that are called by the router when it responds to HTTP requests.

Those are tested by sending HTTP requests with integration and system tests to your application.

Writing controller tests is a highly flawed and outdated approach that is not recommended by the Rails core team. Isolating controllers is actually very hard as they are Rack applications and have a hard dependency on an incoming request and the Rack middleware stack. Its also not a good idea as the extensive mocking required lets bugs slip through.

If you have a method that you want to call from the outside it does not belong in the controller. Put it in a model, service object or anywhere else where its actually easy to test it isolation.

Controllers have tons of responsibilities already. Don't turn them into the junk drawers of your application.

  • Related