Chapter 4 stubs

library("webmockr")

set return objects

stub_request("get", "https://httpbin.org/get") %>%
  wi_th(
    query = list(hello = "world")) %>%
    to_return(status = 418)
#> <webmockr stub> 
#>   method: get
#>   uri: https://httpbin.org/get
#>   with: 
#>     query: hello=world
#>     body: 
#>     request_headers: 
#>   to_return: 
#>     status: 418
#>     body: 
#>     response_headers: 
#>   should_timeout: FALSE
#>   should_raise: FALSE
x$get('get', query = list(hello = "world"))
#> <crul response> 
#>   url: https://httpbin.org/get?hello=world
#>   request_headers: 
#>     User-Agent: libcurl/7.64.1 r-curl/4.3 crul/0.9.0
#>     Accept-Encoding: gzip, deflate
#>     Accept: application/json, text/xml, application/xml, */*
#>   response_headers: 
#>   params: 
#>     hello: world
#>   status: 418

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"))
#> <webmockr stub> 
#>   method: get
#>   uri: https://httpbin.org/get
#>   with: 
#>     query: hello=world
#>     body: 
#>     request_headers: User-Agent=libcurl/7.51.0 r-cur..., Accept-Encoding=gzip, deflate
#>   to_return: 
#>     status: 
#>     body: 
#>     response_headers: 
#>   should_timeout: FALSE
#>   should_raise: FALSE
stub_registry()
#> <webmockr stub registry> 
#>  Registered Stubs
#>    GET: https://httpbin.org/get 
#>    GET: https://httpbin.org/get?hello=world   | to_return:   with status 418 
#>    GET: https://httpbin.org/get?hello=world   with headers {"User-Agent":"libcurl/7.51.0 r-curl/2.6 crul/0.3.6","Accept-Encoding":"gzip, deflate"}
x <- HttpClient$new(url = "https://httpbin.org")
x$get('get', query = list(hello = "world"))
#> <crul response> 
#>   url: https://httpbin.org/get?hello=world
#>   request_headers: 
#>     User-Agent: libcurl/7.64.1 r-curl/4.3 crul/0.9.0
#>     Accept-Encoding: gzip, deflate
#>     Accept: application/json, text/xml, application/xml, */*
#>   response_headers: 
#>   params: 
#>     hello: world
#>   status: 418

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')
#> Error: Request Timeout (HTTP 408).
#>  - The client did not produce a request within the time that the server was prepared
#>    to wait. The client MAY repeat the request without modifications at any later time.

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"))
#> Error: Bad Request (HTTP 400).
#>  - The request could not be understood by the server due to malformed syntax.
#>    The client SHOULD NOT repeat the request without modifications.

4.1 Writing to disk

There are two ways to deal with mocking writing to disk. First, you can create a file with the data you’d like in that file, then tell crul or httr where that file is. Second, you can simply give webmockr a file path (that doesn’t exist yet) and some data, and webmockr can take care of putting the data in the file.

Here’s the first method, where you put data in a file as your mock, then pass the file as a connection (with file(<file path>)) to to_return().

## make a temp file
f <- tempfile(fileext = ".json")
## write something to the file
cat("{\"hello\":\"world\"}\n", file = 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)
## view stubbed file content
readLines(file(f))
#> [1] "{\"hello\":\"world\"}"

With the second method, use webmockr::mock_file() to have webmockr handle file and contents.

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

webmockr also supports httr::write_disk(), here letting webmockr handle the mock file creation:

library(httr)
httr_mock()
## make a temp file
f <- tempfile(fileext = ".json")
## make the stub
invisible(stub_request("get", "https://httpbin.org/get?cheese=swiss") %>% 
  to_return(
    body = mock_file(path = f, payload = "{\"foo\": \"bar\"}"),
    headers = list('content-type' = "application/json")
  ))
## make a request
out <- GET("https://httpbin.org/get?cheese=swiss", write_disk(f, TRUE))
## view stubbed file content
readLines(out$content)
#> [1] "{\"foo\": \"bar\"}"