webmockr

Stub and set expectations on HTTP requests

https://github.com/ropensci/webmockr

Science Score: 26.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (14.7%) to scientific vocabulary

Keywords

fakeweb http http-mock http-mocking mock r r-package rstats tdd testing testing-tools

Keywords from Contributors

genome biodiversity taxonomy reproducibility biology darwincore nomenclature taxize antweb bison
Last synced: 4 months ago · JSON representation

Repository

Stub and set expectations on HTTP requests

Basic Info
Statistics
  • Stars: 50
  • Watchers: 5
  • Forks: 8
  • Open Issues: 14
  • Releases: 21
Topics
fakeweb http http-mock http-mocking mock r r-package rstats tdd testing testing-tools
Created about 11 years ago · Last pushed 5 months ago
Metadata Files
Readme Changelog Contributing License Codemeta

README.Rmd

webmockr
========

```{r echo=FALSE}
knitr::opts_chunk$set(
  comment = "#>",
  collapse = TRUE,
  warning = FALSE
)
```



[![cran checks](https://badges.cranchecks.info/worst/webmockr.svg)](https://CRAN.R-project.org/package=webmockr)
[![Project Status: Active - The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
[![R-CMD-check](https://github.com/ropensci/webmockr/workflows/R-CMD-check/badge.svg)](https://github.com/ropensci/webmockr/actions/)
[![codecov](https://codecov.io/gh/ropensci/webmockr/branch/main/graph/badge.svg?token=1zWlEQbaEh)](https://app.codecov.io/gh/ropensci/webmockr)
[![rstudio mirror downloads](https://cranlogs.r-pkg.org/badges/webmockr)](https://github.com/r-hub/cranlogs.app)
[![cran version](https://www.r-pkg.org/badges/version/webmockr)](https://cran.r-project.org/package=webmockr)


R library for stubbing and setting expectations on HTTP requests.

Port of the Ruby gem [webmock](https://github.com/bblimke/webmock)

How it works in detail

```{r details, child="details.html"} ```

## Features * Stubbing HTTP requests at low http client lib level * Setting and verifying expectations on HTTP requests * Matching requests based on method, URI, headers and body * Can be used for testing or outside of a testing context * Supports async http request mocking with `crul` only ## Supported HTTP libraries * [crul](https://github.com/ropensci/crul) * [httr](https://github.com/r-lib/httr) * [httr2](https://github.com/r-lib/httr2) ## Install from cran ```{r eval=FALSE} install.packages("webmockr") ``` Dev version ```{r eval=FALSE} # install.packages("pak") pak::pak("ropensci/webmockr") ``` ```{r} library(webmockr) ``` ## Enable webmockr ```{r} webmockr::enable() ``` ## Inside a test framework ```{r} 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!") ``` ```{r echo=FALSE} stub_registry_clear() ``` ## Outside a test framework ```{r} library(crul) ``` ### Stubbed request based on uri only and with the default response ```{r} stub_request("get", "https://httpbin.org/get") ``` ```{r} x <- HttpClient$new(url = "https://httpbin.org") x$get('get') ``` set return objects ```{r} stub_request("get", "https://httpbin.org/get") %>% wi_th( query = list(hello = "world") ) %>% to_return(status = 418) ``` ```{r} x$get('get', query = list(hello = "world")) ``` ### Stubbing requests based on method, uri and query params ```{r} 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" ) ) ``` ```{r} stub_registry() ``` ```{r} x <- HttpClient$new(url = "https://httpbin.org") x$get('get', query = list(hello = "world")) ``` ### Stubbing requests and set expectation of a timeout ```{r error=TRUE} 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 ```{r error=TRUE} 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 ```{r} library(webmockr) library(httr) # turn on httr mocking httr_mock() ``` ```{r eval=FALSE} # 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 ```{r} 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 ```{r eval=FALSE} (res <- GET("https://httpbin.org/get")) res$status_code #> [1] 418 res$headers #> $im_a #> [1] "teapot" ``` ## httr2 integration ```{r message=FALSE} library(webmockr) library(httr2) # turn on httr2 mocking enable() ``` ```{r eval=FALSE} # no stub found req <- request("https://hb.opencpu.org/get") req_perform(req) #> Error: Real HTTP connections are disabled. #> Unregistered request: #> GET https://hb.opencpu.org/get #> #> You can stub this request with the following snippet: #> #> stub_request('get', uri = 'https://hb.opencpu.org/get') #> ============================================================ ``` make a stub ```{r} stub_request('get', uri = 'https://hb.opencpu.org/get') %>% to_return( status = 418, body = "I'm a teapot!!!", headers = list(im_a = "teapot") ) ``` now returns mocked response ```{r eval=FALSE} req <- request("https://hb.opencpu.org/get") res <- req_perform(req) res res$status_code #> [1] 418 res$headers #> #> im_a: teapot ``` ## Writing to disk Write to a file before mocked request ```{r echo=FALSE} stub_registry_clear() request_registry_clear() ``` ```{r} ## 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 ```{r} 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 `crul`, `httr`, and `httr2` ## Many requests in a row e.g., many redirects, then a final successful request ```{r eval=FALSE} 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 * [Scott Chamberlain](https://github.com/sckott) * [Aaron Wolen](https://github.com/aaronwolen) ## Meta * Please [report any issues or bugs](https://github.com/ropensci/webmockr/issues). * License: MIT * Get citation information for `webmockr` in R doing `citation(package = 'webmockr')` * Please note that this package is released with a [Contributor Code of Conduct](https://ropensci.org/code-of-conduct/). By contributing to this project, you agree to abide by its terms.

Owner

  • Name: rOpenSci
  • Login: ropensci
  • Kind: organization
  • Email: info@ropensci.org
  • Location: Berkeley, CA

CodeMeta (codemeta.json)

{
  "@context": "https://doi.org/10.5063/schema/codemeta-2.0",
  "@type": "SoftwareSourceCode",
  "identifier": "webmockr",
  "description": "Stubbing and setting expectations on 'HTTP' requests. Includes tools for stubbing 'HTTP' requests, including expected request conditions and response conditions. Match on 'HTTP' method, query parameters, request body, headers and more. Can be used for unit tests or outside of a testing context.",
  "name": "webmockr: Stubbing and Setting Expectations on 'HTTP' Requests",
  "relatedLink": [
    "https://books.ropensci.org/http-testing/",
    "https://docs.ropensci.org/webmockr/"
  ],
  "codeRepository": "https://github.com/ropensci/webmockr",
  "issueTracker": "https://github.com/ropensci/webmockr/issues",
  "license": "https://spdx.org/licenses/MIT",
  "version": "2.2.0",
  "programmingLanguage": {
    "@type": "ComputerLanguage",
    "name": "R",
    "url": "https://r-project.org"
  },
  "runtimePlatform": "R version 4.5.1 (2025-06-13)",
  "provider": {
    "@id": "https://cran.r-project.org",
    "@type": "Organization",
    "name": "Comprehensive R Archive Network (CRAN)",
    "url": "https://cran.r-project.org"
  },
  "author": [
    {
      "@type": "Person",
      "givenName": "Scott",
      "familyName": "Chamberlain",
      "email": "myrmecocystus+r@gmail.com",
      "@id": "https://orcid.org/0000-0003-1444-9135"
    }
  ],
  "contributor": [
    {
      "@type": "Person",
      "givenName": "Aaron",
      "familyName": "Wolen",
      "@id": "https://orcid.org/0000-0003-2542-2202"
    }
  ],
  "funder": [
    {
      "@type": "Organization",
      "name": "rOpenSci"
    }
  ],
  "maintainer": [
    {
      "@type": "Person",
      "givenName": "Scott",
      "familyName": "Chamberlain",
      "email": "myrmecocystus+r@gmail.com",
      "@id": "https://orcid.org/0000-0003-1444-9135"
    }
  ],
  "softwareSuggestions": [
    {
      "@type": "SoftwareApplication",
      "identifier": "testthat",
      "name": "testthat",
      "version": ">= 3.0.0",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=testthat"
    },
    {
      "@type": "SoftwareApplication",
      "identifier": "xml2",
      "name": "xml2",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=xml2"
    },
    {
      "@type": "SoftwareApplication",
      "identifier": "crul",
      "name": "crul",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=crul"
    },
    {
      "@type": "SoftwareApplication",
      "identifier": "httr",
      "name": "httr",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=httr"
    },
    {
      "@type": "SoftwareApplication",
      "identifier": "httr2",
      "name": "httr2",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=httr2"
    },
    {
      "@type": "SoftwareApplication",
      "identifier": "diffobj",
      "name": "diffobj",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=diffobj"
    },
    {
      "@type": "SoftwareApplication",
      "identifier": "withr",
      "name": "withr",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=withr"
    }
  ],
  "softwareRequirements": {
    "1": {
      "@type": "SoftwareApplication",
      "identifier": "R",
      "name": "R",
      "version": ">= 4.1.0"
    },
    "2": {
      "@type": "SoftwareApplication",
      "identifier": "curl",
      "name": "curl",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=curl"
    },
    "3": {
      "@type": "SoftwareApplication",
      "identifier": "jsonlite",
      "name": "jsonlite",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=jsonlite"
    },
    "4": {
      "@type": "SoftwareApplication",
      "identifier": "magrittr",
      "name": "magrittr",
      "version": ">= 1.5",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=magrittr"
    },
    "5": {
      "@type": "SoftwareApplication",
      "identifier": "R6",
      "name": "R6",
      "version": ">= 2.1.3",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=R6"
    },
    "6": {
      "@type": "SoftwareApplication",
      "identifier": "urltools",
      "name": "urltools",
      "version": ">= 1.6.0",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=urltools"
    },
    "7": {
      "@type": "SoftwareApplication",
      "identifier": "fauxpas",
      "name": "fauxpas",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=fauxpas"
    },
    "8": {
      "@type": "SoftwareApplication",
      "identifier": "rlang",
      "name": "rlang",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=rlang"
    },
    "9": {
      "@type": "SoftwareApplication",
      "identifier": "cli",
      "name": "cli",
      "provider": {
        "@id": "https://cran.r-project.org",
        "@type": "Organization",
        "name": "Comprehensive R Archive Network (CRAN)",
        "url": "https://cran.r-project.org"
      },
      "sameAs": "https://CRAN.R-project.org/package=cli"
    },
    "SystemRequirements": null
  },
  "applicationCategory": "Web",
  "isPartOf": "https://ropensci.org",
  "keywords": [
    "http",
    "https",
    "API",
    "web-services",
    "curl",
    "mock",
    "mocking",
    "fakeweb",
    "http-mocking",
    "testing",
    "testing-tools",
    "tdd"
  ],
  "fileSize": "395.679KB"
}

GitHub Events

Total
  • Create event: 8
  • Release event: 2
  • Issues event: 26
  • Watch event: 1
  • Issue comment event: 25
  • Push event: 57
  • Pull request event: 6
  • Fork event: 2
Last Year
  • Create event: 8
  • Release event: 2
  • Issues event: 26
  • Watch event: 1
  • Issue comment event: 25
  • Push event: 57
  • Pull request event: 6
  • Fork event: 2

Committers

Last synced: 7 months ago

All Time
  • Total Commits: 504
  • Total Committers: 6
  • Avg Commits per committer: 84.0
  • Development Distribution Score (DDS): 0.081
Past Year
  • Commits: 78
  • Committers: 3
  • Avg Commits per committer: 26.0
  • Development Distribution Score (DDS): 0.038
Top Committers
Name Email Commits
Scott Chamberlain m****s@g****m 463
Aaron Wolen a****n@w****m 32
Maëlle Salmon m****n@y****e 3
Jeroen Ooms j****s@g****m 3
Hadley Wickham h****y@p****o 2
Hugo Gruson h****n@p****m 1
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 4 months ago

All Time
  • Total issues: 123
  • Total pull requests: 32
  • Average time to close issues: 7 months
  • Average time to close pull requests: about 15 hours
  • Total issue authors: 17
  • Total pull request authors: 6
  • Average comments per issue: 1.93
  • Average comments per pull request: 1.34
  • Merged pull requests: 31
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 19
  • Pull requests: 11
  • Average time to close issues: 25 days
  • Average time to close pull requests: about 14 hours
  • Issue authors: 4
  • Pull request authors: 2
  • Average comments per issue: 0.89
  • Average comments per pull request: 0.45
  • Merged pull requests: 10
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • sckott (97)
  • maelle (7)
  • hlapp (3)
  • aaronwolen (3)
  • dgkf (2)
  • kenahoo (2)
  • nbenn (1)
  • EHJ-52n (1)
  • hadley (1)
  • russbiggs (1)
  • karawoo (1)
  • matthewcornell (1)
  • davidorme (1)
  • juliasilge (1)
  • mdneuzerling (1)
Pull Request Authors
  • sckott (15)
  • hadley (10)
  • aaronwolen (5)
  • maelle (1)
  • Bisaloo (1)
  • nbenn (1)
Top Labels
Issue Labels
bug (19) adapter (5) docs (2) help wanted (1) use case (1)
Pull Request Labels
adapter (2)

Packages

  • Total packages: 1
  • Total downloads:
    • cran 4,004 last-month
  • Total docker downloads: 131,493
  • Total dependent packages: 23
  • Total dependent repositories: 47
  • Total versions: 21
  • Total maintainers: 1
cran.r-project.org: webmockr

Stubbing and Setting Expectations on 'HTTP' Requests

  • Versions: 21
  • Dependent Packages: 23
  • Dependent Repositories: 47
  • Downloads: 4,004 Last month
  • Docker Downloads: 131,493
Rankings
Docker downloads count: 0.0%
Dependent packages count: 3.1%
Average: 3.7%
Dependent repos count: 3.7%
Downloads: 7.8%
Maintainers (1)
Last synced: 5 months ago