2012-12-06 61 views
2

在Sinatra中工作时,本地对象request已创建并可供所有视图和帮助程序使用。所以,我可以作出ApplicationHelper模块的辅助方法,如果helper方法被称为视图,他们可以反过来调用request对象,像这样:Ruby:模拟本地对象以测试模块方法

module ApplicationHelper 
    def nav_link_to(text,path) 
    path == request.path_info ? klass = 'class="current"' : klass = '' 
    %Q|<a href="#{path}" #{klass}>#{text}</a>| 
    end 
end 

现在,我想测试这一点,但在我的测试中request对象不存在。我试图嘲笑它,但没有奏效。这是我的测试到目前为止:

require 'minitest_helper' 
require 'helpers/application_helper' 

describe ApplicationHelper do 

    before :all do 
    @helper = Object.new 
    @helper.extend(ApplicationHelper) 
    end 

    describe "nav links" do 
    before :each do 
     request = MiniTest::Mock.new 
     request.expect :path_info, '/' 
    end 

    it "should return a link to a path" do 
     @helper.nav_link_to('test','/test').must_equal '<a href="/test">test</a>' 
    end 

    it "should return an anchor link to the current path with class 'current'" do 
     @helper.nav_link_to('test','/').must_equal '<a href="test" class="current">test</a>' 
    end 
    end 
end 

那么,你怎么能嘲笑一个'本地'对象,以便你的测试可以调用它的代码?

回答

2

您需要确保@helper对象上有一个返回模拟请求对象的request方法。

在RSpec中,我只是将它存根。我不是特别熟悉MINITEST,但咋一看认为,这可能会在最新版本的工作(如果你在before :each改变request@request):

it "should return a link to a path" do 
    @helper.stub :request, @request do 
    @helper.nav_link_to('test','/test').must_equal '<a href="/test">test</a>' 
    end 
end 

更新

由于MINITEST要求在对象上已经定义了残桩方法,则可以使@helperStruct.new(:request)的实例而不是Object,即

@helper = Struct.new(:request).new 

实际上,这样做可能根本就不需要存根!你可以做

before :each do 
    @helper.request = MiniTest::Mock.new 
    @helper.request.expect :path_info, '/' 
end 
+0

这是有道理的,唯一的问题是MiniTest存根需要该方法已经存在,如果我通常在模块上定义它,它会覆盖实际应用中我想要的一个...所以,这几乎让我在那里,现在我需要仔细研究一下 – Andrew

+0

啊,好的。你可以做'@helper = Struct.new(:request).new' –

+0

噢,这可能比我有更好的想法!我在想'@helper.instance_eval {def request;零;结束;}'...让我看看你的方法真的很快 – Andrew