Skip to content

How can one mock API errors? #252

@JBGruber

Description

@JBGruber

Quick question (and reporting my confusion about the behaviour): How could I test a custom error message for an API function? It looks like with_mock() gobbles errors. Is there a way around that? I checked your tests, but could not find one that tests the actual error output.

Here is a reproducible example:

library(testthat)
library(httr2)
#> 
#> Attaching package: 'httr2'
#> The following objects are masked from 'package:testthat':
#> 
#>     local_mock, with_mock

api_fun <- function(url, api_key = NULL) {
  req <- httr2::request(url) |>
    httr2::req_method("POST") |>
    httr2::req_headers(
      "Content-Type" = "application/json",
      "Authorization" = glue::glue("Bearer {api_key}")
    ) |>
    httr2::req_error(body = error_body)
  
  httr2::req_perform(req)
}

error_body <- function(resp) {
  msg <- httr2::resp_status(resp)
  if (resp_status(resp) == 429) {
    msg <- c(msg, "This error can also mean that you ran out of API credit.")
  }
  return(msg)
}

# shows correct error
api_fun("https://httpbin.org/status/429")
#> Error:
#> ! Timeout was reached: [httpbin.org] Failed to connect to httpbin.org port 443 after 10001 ms: Timeout was reached
#> Backtrace:
#>     ▆
#>  1. └─global api_fun("https://httpbin.org/status/429")
#>  2.   └─httr2::req_perform(req)
#>  3.     └─base::tryCatch(...)
#>  4.       └─base (local) tryCatchList(expr, classes, parentenv, handlers)
#>  5.         └─base (local) tryCatchOne(expr, names, parentenv, handlers[[1L]])
#>  6.           └─value[[3L]](cond)

mock_error <- function(...) {
  httr2::response(429)
}

# does not error with with_mock
expect_error(
  with_mock(mock = mock_error, code = api_fun("https://httpbin.org/status/429")),
  "This error can also mean that you ran out of API credit."
)
#> Error: `with_mock(mock = mock_error, code = api_fun("https://httpbin.org/status/429"))` did not throw an error.

Created on 2023-07-11 with reprex v2.0.2

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugan unexpected problem or unintended behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions