Search code examples
rapihttpmockingtestthat

How to mock http response of rest API?


I am looking for the easiest way to mock response of rest API within testthat framework.

Example of usage would be similar to this:

with_mock_api(
  request, 
  response, 
  {
      call_to_function_with_api_call()
      # expectations check
  }
)

As a result, tests will pass without calling the real API.

  • request refers to the definition of http request that will be done inside of the api wrapper function;
  • response refers to the response object that has been cached for the purpose of mocking.

Solution

  • https://github.com/ropensci/vcr makes this pretty easy. Supports integration with crul as well as httr.

    A function that makes an API request

    foo_bar <- function() {
      x <- crul::HttpClient$new("https://httpbin.org")
      res <- x$get("get", query = list(foo = "bar"))
      jsonlite::fromJSON(res$parse("UTF-8"))
    }
    

    Then run any functions inside of a vcr::use_cassette block, and run any testthat expectations on the output as usual

    library(testthat)
    test_that("my_test", {
      vcr::use_cassette("foo_bar", {
        aa <- foo_bar()
      })
    
      expect_is(aa, "list")
      expect_named(aa, c("args", "headers", "origin", "url"))
      expect_equal(aa$args$foo, "bar")
    })
    

    The request and response gets stored in a yaml file - see https://github.com/ropensci/vcr#usage for an example. - On the 1st run of the code above, a real HTTP request will be made to make that yaml file, BUT on the 2nd and all subsequent runs afterwards, no real HTTP requests are made, but instead the function uses that yaml file.