0

为了单元测试的目的,我有一个方法mock_request被覆盖。对于每个请求,我想执行一些代码:

def mock_request(method, url, params={})
  case "#{method} #{url}"
  when 'post /customers'
    # create customer
  when %r{post /customers/(.*)/items}
    id = $1 # update customer
  when %r{post /customers/(.*)}
    id = $1 # update customer
  else
    throw 'Unrecognized request'
  end
end

问题是这个case语句变得很长,每个case的行数都在慢慢增加。此外,同时处理多个模型。

我想做的是为每个模型设置单独的文件,并以某种方式将它们包含在此mock_request方法中。像这样的东西:

# handlers/customers.rb
module RequestHandlers
  # post /customers
  # post /customers/(.*)
end

# handlers/items.rb
module RequestHandlers
  # post /customers/(.*)/items
end

# mock_request.rb
class MockServer
  def mock_request(method, url, params={})
    handle_request(method, url)
  end
end

但是我不确定如何实现这一点。在红宝石中解决这个问题的最佳方法是什么?

4

2 回答 2

1

您可以创建一个散列,其中包含方法和 URL 字符串作为键,以及要评估的代码块作为值。

def mock_request(method, url, params={})
 #create a request hash where the default value is your else, this way if a key that doesn't exist is called, the unrecognized request is called

  req =  Hash.new ({throw 'Unrecognized request'})
  req['post /customers'] = {#create customer block/proc}
  req[%r{post /customers/(.*)/items}] = {#update customer block/proc}

  req["#{method} #{url}"]
end

这对您来说可能是一个更好的选择,并且可以让您摆脱冗长的案例陈述。

于 2013-05-17T13:55:18.723 回答
0

作为记录,这就是我最终重构它的方式。

处理程序的每个“主题”都有自己的模块和文件:

module RequestHandlers
  module Customers

    def Customers.included(mock_server)
      mock_server.add_handler 'post /customers',      :new_customer
      mock_server.add_handler 'post /customers/(.*)', :update_customer
    end

    def new_customer(route, method_url, params)
      # create new customer
    end

    def update_customer(route, method_url, params)
      # update existing customer
    end

  end
end

主类是处理程序生活和使用的地方:

class MockServer

  # Handlers are ordered by priority
  @@handlers = []

  include RequestHandlers::Customers
  include RequestHandlers::Items
  # etc.

  def self.add_handler(route, name)
    @@handlers << {
      :route => %r{^#{route}$},
      :name => name
    }
  end

  def mock_request(method, url, params={})
    method_url = "#{method} #{url}"
    handler = @@handlers.find {|h| method_url =~ h[:route] }

    if handler
      self.send(handler[:name], handler[:route], method_url, params)
    else
      throw 'Unrecognized request'
    end
  end
end
于 2013-06-05T19:38:01.803 回答