Mocking / Stubbing application controller method using Mocha (using Shoulda, Rails 3)

When writing functional tests for the controller, I came across a script where I have a before_filter requesting some information from a database that one of my tests requires. I use Factory_girl to generate test data, but I want to avoid getting into the database when it is clearly not needed. I would also like to avoid testing my before_filter method (I plan to test it in a separate test). As I understand it, ridicule / step is a way to do it.

My question is what is the best way to cheat / drown this method in this scenario.

My before filter method looks for a site in db based on the subdomain found in the url and sets the instance variable that will be used in the controller:


#application_controller.rb

def load_site_from_subdomain
  @site = Site.first(:conditions => { :subdomain => request.subdomain })
end

My controller that uses this method as before_filter:


# pages_controller.rb

before_filter :load_site_from_subdomain

def show
  @page = @site.pages.find_by_id_or_slug(params[:id]).first
  respond_to do |format|
    format.html { render_themed_template }
    format.xml  { render :xml => @page }
  end
end

As you can see, it relies on a variable @siteto be set (using before_filter). However, during testing, I would like the test to assume that it is @siteinstalled and that it has at least 1 linked page (found @site.pages). I would then check out my method load_site_from_subdomainlater.

Here is what I have in my testing (using Shoulda and Mocha):


context "a GET request to the #show action" do

  setup do
    @page = Factory(:page)
    @site = Factory.build(:site)

    # stub out the @page.site method so it doesn't go 
    # looking in the db for the site record, this is
    # used in this test to add a subdomain to the URL
    # when requesting the page
    @page.stubs(:site).returns(@site)

    # this is where I think I should stub the load_site_from_subdomain
    # method, so the @site variable will still be set
    # in the controller. I'm just not sure how to do that.
    @controller.stubs(:load_site_from_subdomain).returns(@site)

    @request.host = "#{ @page.site.subdomain }.example.com"
    get :show, :id => @page.id
  end

  should assign_to(:site)
  should assign_to(:page)
  should respond_with(:success)

end

This leaves me with an error in my test results, telling me that it @siteis zero.

, . , Factory.create , db, , , db, .

+3
2

"Site.first", @site var, , var before_filter.

+1

, @site nil, load_site_from_subdomain @site - , stubbing load_site_from_subdomain @site. :

:

load_site_from_subdomain, :

def load_site_from_subdomain
  Site.first(:conditions => { :subdomain => request.subdomain })
end

before_filter :load_site_from_subdomain show :

def show
  @site = load_site_from_subdomain
  @page = @site.pages.find_by_id_or_slug(params[:id]).first
  respond_to do |format|
    format.html { render_themed_template }
    format.xml  { render :xml => @page }
  end
end

:

@controller.stubs(:load_site_from_subdomain).returns(@site)

, @site load_site_from_subdomain

Site.first, , , , , respond. , , :

Site.stubs(:first).returns(@site)
0

Source: https://habr.com/ru/post/1767957/


All Articles