Minitest with Kaminari

While converting my tests from FactoryGirl.create to FactoryGirl.build_stubbed, I ran into trouble with Kaminari. Here’s how I fixed it.

Kaminari

Kaminari functions by adding .page() (and some other methods) at the end of your ActiveRecord call chain. A typical example of paginating via Kaminari is as follows:

class UsersController < ApplicationController
  def active_users
    @users = User.active_users.page(params[:page])
  end
end

This is a problem when you’re trying to stub out the return of the AR call to return an array. Here’s a corresponding test that would fail:

require 'test_helper'

describe UsersController, "#active_users" do
  test "success" do
    users = FactoryGirl.build_list :user, 3
    User.expects(:active).returns(users)
    get :search, term: "admin_user"
    assert_response :success
  end
end

Because users is just a regular array here, and Kaminari tries to call .page() on the array, it would fail with a NoMethodError: undefined method `page’ for # because Array#page isn’t defined.

Trying to stub out .page() by users.stubs(page: users) would give you ActionView::Template::Error: undefined method `model_name’ for #. And so on, as long as you’re using Kaminari-specific methods.

The solution

The solution is pretty simple (but took me 2+ hours to research). Call Kaminari.paginate_array on the FactoryGirl.build_list.

users = Kaminari.paginate_array FactoryGirl.build_list :user, 3

From the documentation:

Kaminari::paginate_array method converts your Array object into a paginatable Array that accepts page method.

For now, I’m putting the Kaminari.paginate_array inside the test, but long term, it makes sense to put it in the controller code. This way, even if we change User.active to return an array, no other code would break. Then again, that’s why we have tests, right?