Puppet rspec测试中的模拟方法

时间:2014-04-18 16:00:29

标签: ruby unit-testing rspec puppet

我已经实现了一个自定义Puppet函数,可以查询Keystone服务器以获取信息。定义此函数的模块包括一些辅助方法,用于执行查询keystone的实际工作。从广义上讲,结构如下:

def authenticate(auth_url, username, password)
...
end

def list_tenants(auth_url, token)
...
end

module Puppet::Parser::Functions
    newfunction(:lookup_tenant, :type => :rvalue) do |args|
    ...
    end
end

我想嘲笑authenticatelist_tenants方法 在测试期间,我可以测试其余的Puppet模块 没有实际的Keystone服务器。

我以前从未使用过Ruby或Rpsec,而且我还没有 很难找到如何为这些提供存根的示例 内部方法。

到目前为止,我有一个存根rspec文件,只是验证了存在 功能:

require 'spec_helper'

describe 'lookup_tenant' do
    it "should exist" do
        Puppet::Parser::Functions.function("lookup_tenant").should == "function_lookup_tenant"
    end

    # This will fail because there is no keystone server.
    it "should fail" do
        should run.with_params(
            'http://127.0.0.1:35357/v2.0',
            'admin_user',
            'admin_password',
            'admin_tenant_name',
            'target_tenant_name'
       ).and_raise_error(KeystoneError)
    end
end

我希望能够提供自定义退货 authenticatelist_tenants方法(甚至引发异常 从这些方法里面)这样我就可以测试它的行为了 lookup_tenant在不同的故障情况下发挥作用。

2 个答案:

答案 0 :(得分:1)

WebMock可用于将http请求模拟为存根。以下是github repo的链接:https://github.com/bblimke/webmock

答案 1 :(得分:1)

对于以前没有见过webmock的人,我想在此留一些关于它为何特别棒的信息。

所以,我在我的模块中有一些代码发出了一个http请求:

url = URI.parse("#{auth_url}/tokens")
req = Net::HTTP::Post.new url.path
req['content-type'] = 'application/json'
req.body = JSON.generate(post_args)

begin
    res = Net::HTTP.start(url.host, url.port) {|http|
        http.request(req)
    }

    if res.code != '200'
        raise KeystoneError, "Failed to authenticate to Keystone server at #{auth_url} as user #{username}."
    end
rescue Errno::ECONNREFUSED
    raise KeystoneError, "Failed to connect to Keystone server at #{auth_url}."
end

只需在规范文件的开头添加require

require `webmock`

尝试打开连接将导致:

 WebMock::NetConnectNotAllowedError:
   Real HTTP connections are disabled. Unregistered request: POST http://127.0.0.1:35357/v2.0/tokens with body '{"auth":{"passwordCredentials":{"username":"admin_user","password":"admin_password"},"tenantName":"admin_tenant"}}' with headers {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/json', 'User-Agent'=>'Ruby'}

   You can stub this request with the following snippet:

   stub_request(:post, "http://127.0.0.1:35357/v2.0/tokens").
     with(:body => "{\"auth\":{\"passwordCredentials\":{\"username\":\"admin_user\",\"password\":\"admin_password\"},\"tenantName\":\"admin_tenant\"}}",
          :headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/json', 'User-Agent'=>'Ruby'}).
     to_return(:status => 200, :body => "", :headers => {})

这就是你需要的所有信息 呼叫。您可以根据需要将存根设置为粒度;我结束了 使用类似的东西:

good_auth_request = { 
    'auth' => {
        'passwordCredentials' => {
            'username' => 'admin_user',
            'password' => 'admin_password',
        },
        'tenantName' => 'admin_tenant',
    }
}

auth_response = {
    'access' => {
        'token' => {
            'id' => 'TOKEN',
        }
    }
}

stub_request(:post, "http://127.0.0.1:35357/v2.0/tokens").
    with(:body => good_auth_request.to_json).
    to_return(:status => 200, :body => auth_response.to_json, :headers => {})

现在我可以在没有Keystone服务器的情况下测试我的模块 可用。