Back

ruby - VCR gem的使用 mock http request

发布时间: 2022-10-25 03:01:00

refer to:  
https://relishapp.com/vcr/vcr/v/6-1-0/docs/getting-started

VCR用来使用mock http request的。 

使用方法很简单:

在  test/test_helper.rb 或者对应的rspec文件中:

require 'vcr'

VCR.configure do |c|
  c.cassette_library_dir = 'vcr_cassettes'   # 指定生成的yml 文件的路径
  c.hook_into :webmock
end

然后在unit test中,使用一个 block 就会自动使用了:

VCR.use_cassette('whatever cassette name you want') do
   # the body of the test would go here...
   # 例如   
   #  response = HTTParty.get 'www.baidu.com'
   #  assert response.code == '200'
end

同时,会生成对应的 mock http response 文件,例如:

---
http_interactions:
- request:
    method: get
    uri: http://example.com/
    body: ''
    headers: {}
  response:
    status:
      code: 200
      message: OK
    headers:
      Content-Type:
      - text/html;charset=utf-8
      Content-Length:
      - '26'
    body: This is the response body
    http_version: '1.1'
  recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
recorded_with: VCR 2.0.0

这个gem 很霸道,一旦使用的话, 就默认必须使用VCR block ,否则会报错。

        ================================================================================
        An HTTP request has been made that VCR does not know how to handle:
          POST http://localhost:xx/
          Body: {"id":1,"jsonrpc":"2.0","method":"get_transaction","params":["0xed2049c21ffccfcd26281d60f8f77ff117adb9df9d3f8cbe5fe86e893c66d359"]}

        VCR is currently using the following cassette:
          - /mnt/xx/get_rejected_transaction.yml
            - :record => :once
            - :match_requests_on => [:method, :path, :body]

        Under the current configuration VCR can not find a suitable HTTP interaction
        to replay and is prevented from recording new requests. There are a few ways
        you can deal with this:

          * If you're surprised VCR is raising this error
            and want insight about how VCR attempted to handle the request,
            you can use the debug_logger configuration option to log more details [1].
          * You can use the :new_episodes record mode to allow VCR to
            record this new request to the existing cassette [2].
          * If you want VCR to ignore this request (and others like it), you can
            set an `ignore_request` callback [3].
          * The current record mode (:once) does not allow new requests to be recorded
            to a previously recorded cassette. You can delete the cassette file and re-run
            your tests to allow the cassette to be recorded with this request [4].
          * The cassette contains 2 HTTP interactions that have not been
            played back. If your request is non-deterministic, you may need to
            change your :match_requests_on cassette option to be more lenient
            or use a custom request matcher to allow it to match [5].

解决办法很简单: 

1. 要么使用VCR do ..end 

2. 要么在VCR的配置文件中,增加ignore 选项,例如:

refer to:   https://stackoverflow.com/questions/14885557/vcr-does-not-know-how-to-handle-this-request

  c.ignore_request {|request| request.uri == 'https://accounts.google.com/o/oauth2/token' }

3. 如果还有报错,就检查 yml 文件, 参数有一个地方不对都会报错。例如,几乎所有的JSON RPC,都会有个参数id, 每次加1, 这样的话就不行了。

解决办法: 使用stub 来模拟让对应的方法每次都生成同样的id . 

 4   setup do
  5     YourClass.any_instance.stubs(:generate_json_rpc_id).returns(1)
  6   end

Back