在写功能测试的控制器,我碰到一种情况,我有一个请求的before_filter从数据库中一些信息,我的测试一个要求。我使用Factory_girl生成测试数据,但我想避免进入数据库的不明确需要的时候。我也想避免在这里测试我的before_filter方法(我计划,以测试它在一个单独的测试)。据我所知,嘲笑/存根是做到这一点。

的方式

我的问题是,什么是嘲笑的最佳方法/存根在这种情况下此方法。

我的前滤光器的方法会在基于一个子域的分贝的部位在URL找到并设置一个实例变量在控制器中使用:


#application_controller.rb

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

我的控制器使用该方法作为的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

可以看到,它依赖于要设置的@site变量(由的before_filter)。然而在测试中,我想有测试假设@site已定,并且它具有至少1相关联的页(由@site.pages找到)。我想在稍后然后测试我load_site_from_subdomain方法。

下面是我在我的测试(使用早该&摩卡):


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

这给我留下了一个错误在我的测试结果告诉我,@site是零。

我觉得我要对这个错误的方式。我知道这将是容易的,只需刚Factory.create的网站,以便它在数据库中存在,但正如我刚才所说,我想分贝的使用减少,以帮助保持我的测试迅速。

有帮助吗?

解决方案

尝试删空“Site.first”,因为它的@site VAR的设置,你需要存根,而不是从的before_filter返回的变种。

其他提示

之所以你@sitenil因为你load_site_from_subdomain确实为@site的赋值 - 它不返回任何值,因此您的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)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top