webmockr

knitr::opts_chunk$set(
  comment = "#>",
  collapse = TRUE,
  warning = FALSE
)

cran checks Project Status: Active - The project has reached a stable, usable state and is being actively developed. R-CMD-check codecov rstudio mirror downloads cran version

R library for stubbing and setting expectations on HTTP requests.

Port of the Ruby gem webmock

How it works in detail


Features

Supported HTTP libraries

Install

from cran

install.packages("webmockr")

Dev version

remotes::install_github("ropensci/webmockr")
library(webmockr)

Enable webmockr

webmockr::enable()

Inside a test framework

library(crul)
library(testthat)

# make a stub
stub_request("get", "https://httpbin.org/get") %>%
   to_return(body = "success!", status = 200)

# check that it's in the stub registry
stub_registry()

# make the request
z <- crul::HttpClient$new(url = "https://httpbin.org")$get("get")

# run tests (nothing returned means it passed)
expect_is(z, "HttpResponse")
expect_equal(z$status_code, 200)
expect_equal(z$parse("UTF-8"), "success!")
stub_registry_clear()

Outside a test framework

library(crul)

Stubbed request based on uri only and with the default response

stub_request("get", "https://httpbin.org/get")
x <- HttpClient$new(url = "https://httpbin.org")
x$get('get')

set return objects

stub_request("get", "https://httpbin.org/get") %>%
  wi_th(
    query = list(hello = "world")) %>%
    to_return(status = 418)
x$get('get', query = list(hello = "world"))

Stubbing requests based on method, uri and query params

stub_request("get", "https://httpbin.org/get") %>%
  wi_th(query = list(hello = "world"), 
        headers = list('User-Agent' = 'libcurl/7.51.0 r-curl/2.6 crul/0.3.6', 
                       'Accept-Encoding' = "gzip, deflate"))
stub_registry()
x <- HttpClient$new(url = "https://httpbin.org")
x$get('get', query = list(hello = "world"))

Stubbing requests and set expectation of a timeout

stub_request("post", "https://httpbin.org/post") %>% to_timeout()
x <- HttpClient$new(url = "https://httpbin.org")
x$post('post')

Stubbing requests and set HTTP error expectation

library(fauxpas)
stub_request("get", "https://httpbin.org/get?a=b") %>% to_raise(HTTPBadRequest)
x <- HttpClient$new(url = "https://httpbin.org")
x$get('get', query = list(a = "b"))

httr integration

library(webmockr)
library(httr)

# turn on httr mocking
httr_mock()
# no stub found
GET("https://httpbin.org/get")
#> Error: Real HTTP connections are disabled.
#> Unregistered request:
#>   GET https://httpbin.org/get   with headers {Accept: application/json, text/xml, application/xml, */*}
#> 
#> You can stub this request with the following snippet:
#> 
#>    stub_request('get', uri = 'https://httpbin.org/get') %>%
#>      wi_th(
#>        headers = list('Accept' = 'application/json, text/xml, application/xml, */*')
#>      )
#> ============================================================

make a stub

stub_request('get', uri = 'https://httpbin.org/get') %>%
  wi_th(
    headers = list('Accept' = 'application/json, text/xml, application/xml, */*')
  ) %>%
  to_return(status = 418, body = "I'm a teapot!!!", headers = list(im_a = "teapot"))

now returns mocked response

(res <- GET("https://httpbin.org/get"))
res$status_code
#> [1] 418
res$headers
#> $im_a
#> [1] "teapot"

Writing to disk

Write to a file before mocked request

stub_registry_clear()
request_registry_clear()
## make a temp file
f <- tempfile(fileext = ".json")
## write something to the file
cat("{\"hello\":\"world\"}\n", file = f)
readLines(f)
## make the stub
invisible(stub_request("get", "https://httpbin.org/get") %>% 
  to_return(body = file(f)))
## make a request
out <- HttpClient$new("https://httpbin.org/get")$get(disk = f)
readLines(file(f))

OR - you can use mock_file() to have webmockr handle file and contents

g <- tempfile(fileext = ".json")
## make the stub
invisible(stub_request("get", "https://httpbin.org/get") %>% 
  to_return(body = mock_file(g, "{\"hello\":\"mars\"}\n")))
## make a request
out <- crul::HttpClient$new("https://httpbin.org/get")$get(disk = g)
readLines(out$content)

Writing to disk is supported in both crul and httr

Many requests in a row

e.g., many redirects, then a final successful request

webmockr::enable()
library(crul)
library(fauxpas)

z <- stub_request("get", "https://httpbin.org/get")
to_return(z, status = 200, body = "foobar", headers = list(a = 5))
to_return(z, status = 200, body = "bears", headers = list(b = 6))
to_raise(z, HTTPBadRequest)
z

con <- crul::HttpClient$new(url = "https://httpbin.org")
# the first to_return()
first <- con$get("get")
first
first$parse("UTF-8")
# the second to_return()
second <- con$get("get")
second
second$parse("UTF-8")
# the third to_return() - fails as specified
third <- con$get("get")

Note that subsequent requests past the number of responses given with to_return()/etc. simply gives the last response you specified. Although if you set a to_timeout or to_raise this feature won't happen since you fail out.

Contributors

Meta



ropenscilabs/webmockr documentation built on May 25, 2023, 4:39 a.m.