2012-07-11 25 views
11

Trong thư mục hỗ trợ dưa chuột của tôi, tôi đã điều sau đây trong vcr.rb:của Ruby VCR đá quý vẫn tiếp tục ghi nhận các yêu cầu tương tự

require 'vcr' 

VCR.configure do |c| 
    c.cassette_library_dir = 'fixtures/vcr_cassettes' 
    c.hook_into :webmock 
    c.ignore_localhost = true 
    c.default_cassette_options = { record: :new_episodes } 
end 

tôi mã hóa địa lý tên thành phố mà làm cho các cuộc gọi đến các API của Google Maps. Tôi đang cố gắng để ghi lại và còn sơ khai những yêu cầu này, nhưng nó vẫn không ngừng ghi lại những yêu cầu tương tự cho file yml cùng:

- request: 
    method: get 
    uri: http://maps.googleapis.com/maps/api/geocode/json?address=Miami,%20FL&language=en&sensor=false 
    body: 
     encoding: US-ASCII 
     string: '' 
    headers: 
     Accept-Encoding: 
     - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 
     Accept: 
     - ! '*/*' 
     User-Agent: 
     - Ruby 
    # response... 

- request: 
    method: get 
    uri: http://maps.googleapis.com/maps/api/geocode/json?address=Miami,%20FL&language=en&sensor=false 
    body: 
     encoding: US-ASCII 
     string: '' 
    headers: 
     Accept-Encoding: 
     - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 
     Accept: 
     - ! '*/*' 
     User-Agent: 
     - Ruby 

Đó là cùng một URL và rất tương tự yêu cầu, không nên VCR còn sơ khai theo yêu cầu? Làm thế nào tôi có thể ngăn chặn các thông số kỹ thuật của tôi không truy cập API mỗi khi tôi cố gắng tìm kiếm cùng một thành phố?

Trả lời

21

Thật khó để nói chắc chắn những gì đang diễn ra với những gì bạn đã đăng, nhưng tôi có thể giải thích thêm một chút về cách VCR hoạt động và đưa ra một số dự đoán về các lý do có thể xảy ra hành vi.

VCR sử dụng request matchers để cố gắng tìm một tương tác HTTP đã ghi lại trước đó để phát lại. Trong một phiên băng đơn, khi một tương tác HTTP được phát lại, nó được coi là "được sử dụng" và nó sẽ không được phát lại (trừ khi bạn sử dụng tùy chọn allow_playback_repeats).

... Vì vậy, đây là một vài khả năng mà tôi suy nghĩ:

  • lẽ VCR không thể để phù hợp với các yêu cầu HTTP của bạn. Bạn đang sử dụng đối sánh yêu cầu nào? Có một số cách dễ dàng để khắc phục sự cố này (xem bên dưới).
  • Nếu bạn không sử dụng :allow_playback_repeats (là mặc định và cách tôi khuyên bạn nên sử dụng VCR), thì hành vi bạn thấy có thể xảy ra nếu nhiều yêu cầu trùng lặp đang được thực hiện trong thử nghiệm của bạn - ví dụ: cassette chỉ có một yêu cầu phù hợp nhưng bạn đang thử nghiệm làm cho 2 trong số họ - mà sẽ chơi lại một và ghi lại một (kể từ khi bạn đang sử dụng :new_episodes).

Để khắc phục sự cố này, tôi khuyên bạn nên sử dụng tùy chọn debug_logger để VCR in nội dung đang thực hiện và cách nó cố gắng khớp với từng yêu cầu. Điều đó sẽ cung cấp cho bạn thông tin chi tiết về những gì đang diễn ra. Bạn cũng có thể ghi đè lên bất kỳ the built in request matchers và cung cấp logic riêng của bạn và/hoặc thiết lập một breakpoint trong khớp:

VCR.configure do |c| 
    c.register_request_matcher :uri do |request_1, request_2| 
    debugger # so you can inspect the requests here 
    request_1.uri == request_2.uri 
    end 
end 

Bạn cũng có thể đã chạy vào một lỗi VCR, mặc dù so sánh các URI (sử dụng String#==) là ví dụ một hoạt động cơ bản mà tôi có một thời gian khó tưởng tượng một lỗi ở đó. Vui lòng mở một vấn đề github (hy vọng với đầu ra của trình gỡ lỗi và/hoặc một mẫu mã kích hoạt tính năng này) nếu bạn không thể tìm ra nó.

Lưu ý phụ, tôi khuyên bạn nên sử dụng chế độ bản ghi :once (mặc định) thay vì :new_episodes.:once sẽ không bao giờ ghi lại các tương tác HTTP bổ sung vào băng cassette hiện có - nó chỉ cho phép ghi băng cassette một lần. Nếu yêu cầu không phù hợp, yêu cầu sẽ báo lỗi cho bạn về sự kiện không khớp. :new_episodes, mặt khác, sẽ ghi lại bất kỳ yêu cầu nào mà nó không thể tìm thấy kết quả phù hợp, đó là hành vi bạn đang thấy.

+2

@Erik J - Nếu có * bất kỳ ai * bạn nên nghe về [VCR] (https://github.com/myronmarston/vcr/) đó là một người được gọi là Myron;) – Gareth

+0

Cảm ơn, Myron, tôi hy vọng bạn sẽ trải qua ;) Tôi chỉ nhận ra rằng các tiêu đề phản hồi của tôi bao gồm 'Hết hạn: - Thứ Sáu, ngày 13 tháng 7 năm 2012 18:31:50 GMT', sau 24 giờ kể từ ngày yêu cầu. VCR có nhận thấy điều này và thử thực hiện lại yêu cầu không? Nếu vậy, có cách nào để vô hiệu hóa điều đó không? –

+0

Không, VCR không sử dụng điều này cả. Có tùy chọn [re_record_interval] (https://www.relishapp.com/myronmarston/vcr/v/2-2-3/docs/cassettes/automatic-re-recording) nhưng không xem xét bất kỳ tiêu đề nào (nó chỉ sử dụng khoảng thời gian đã định cấu hình) và nó sẽ không tạo ra các tương tác trùng lặp mà bạn nhìn thấy; nó sẽ thay thế tương tác HTTP cũ thay vì chỉ thêm một cái mới. –

2

Tôi đã gặp phải hành vi tương tự, vì vậy, những gì tôi làm về cơ bản vẫn giữ để đặt thành :none. Nếu có bất kỳ yêu cầu mới nào xuất hiện, tôi sử dụng :any, hãy chạy một phần của bộ kiểm tra đã thực hiện các yêu cầu và đặt lại cho số :none.

Có vẻ như :new_episodes sử dụng một số chẩn đoán lạ để xác định xem yêu cầu mới là gì và yêu cầu nào đã xảy ra. Trong trường hợp của chúng tôi, nó đánh dấu hai yêu cầu khác nhau đối với các cổng thanh toán giống như các cổng thanh toán, dẫn đến các giờ gỡ lỗi vô tận - bởi vì chúng tôi nhận được câu trả lời RefundOk cho một số CaptureRequest và những thứ tương tự. Tốt hơn không sử dụng :new_episodes ...

+0

Thay vì ': all',': none' Toggling bạn đề cập đến, tôi khuyên bạn nên sử dụng ': chế độ ghi hình một lần. Nó hoạt động như ': none' khi một băng cassette đã được ghi lại, hoặc': all' khi nó là một cassette mới. –

+0

Các "heuristics kỳ lạ" bạn đề cập đến cho ': new_episodes' chỉ đơn giản là các đối sánh yêu cầu được cấu hình. Chúng hoạt động tương tự cho tất cả các chế độ ghi. Hiệu ứng của ': new_episodes' là nó sẽ ghi lại các yêu cầu không khớp với bất kỳ yêu cầu nào được ghi lại trước đây; Ngược lại, ': once' và': none' sẽ gây ra lỗi khi điều này xảy ra. –

8

Khi tôi đã có một vấn đề tương tự, tôi cố định nó bằng cách làm cho các thiết lập match_requests_on cụ thể hơn:

VCR.configure do |c| 
    c.default_cassette_options = { 
     match_requests_on: [:uri, :body, :method] 
    } 
end 
Các vấn đề liên quan