{"id":14068661,"url":"https://github.com/ropensci/webmockr","last_synced_at":"2025-10-04T19:38:01.722Z","repository":{"id":23325591,"uuid":"26685722","full_name":"ropensci/webmockr","owner":"ropensci","description":"Stub and set expectations on HTTP requests","archived":false,"fork":false,"pushed_at":"2025-08-05T13:09:56.000Z","size":980,"stargazers_count":50,"open_issues_count":14,"forks_count":8,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-09-23T15:51:42.515Z","etag":null,"topics":["fakeweb","http","http-mock","http-mocking","mock","r","r-package","rstats","tdd","testing","testing-tools"],"latest_commit_sha":null,"homepage":"https://docs.ropensci.org/webmockr","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ropensci.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":"codemeta.json","zenodo":null}},"created_at":"2014-11-15T16:29:29.000Z","updated_at":"2025-08-05T13:10:00.000Z","dependencies_parsed_at":"2023-02-14T01:45:18.098Z","dependency_job_id":"602ded99-6ae5-43e8-8278-f880476c96cf","html_url":"https://github.com/ropensci/webmockr","commit_stats":{"total_commits":456,"total_committers":5,"mean_commits":91.2,"dds":0.08333333333333337,"last_synced_commit":"5cc5c4e815c76c68ac5cc34f3eeafa45dfc206dc"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/ropensci/webmockr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropensci%2Fwebmockr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropensci%2Fwebmockr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropensci%2Fwebmockr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropensci%2Fwebmockr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ropensci","download_url":"https://codeload.github.com/ropensci/webmockr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropensci%2Fwebmockr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278366599,"owners_count":25975091,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-04T02:00:05.491Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fakeweb","http","http-mock","http-mocking","mock","r","r-package","rstats","tdd","testing","testing-tools"],"created_at":"2024-08-13T07:06:19.984Z","updated_at":"2025-10-04T19:38:01.716Z","avatar_url":"https://github.com/ropensci.png","language":"R","funding_links":[],"categories":["R"],"sub_categories":[],"readme":"webmockr\n========\n\n```{r echo=FALSE}\nknitr::opts_chunk$set(\n  comment = \"#\u003e\",\n  collapse = TRUE,\n  warning = FALSE\n)\n```\n\n\u003c!-- NOTE: run `make readme` to generate the README.md --\u003e\n\n[![cran checks](https://badges.cranchecks.info/worst/webmockr.svg)](https://CRAN.R-project.org/package=webmockr)\n[![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)\n[![R-CMD-check](https://github.com/ropensci/webmockr/workflows/R-CMD-check/badge.svg)](https://github.com/ropensci/webmockr/actions/)\n[![codecov](https://codecov.io/gh/ropensci/webmockr/branch/main/graph/badge.svg?token=1zWlEQbaEh)](https://app.codecov.io/gh/ropensci/webmockr)\n[![rstudio mirror downloads](https://cranlogs.r-pkg.org/badges/webmockr)](https://github.com/r-hub/cranlogs.app)\n[![cran version](https://www.r-pkg.org/badges/version/webmockr)](https://cran.r-project.org/package=webmockr)\n\n\nR library for stubbing and setting expectations on HTTP requests.\n\nPort of the Ruby gem [webmock](https://github.com/bblimke/webmock)\n\n\u003cdetails\u003e \u003csummary\u003e\u003cstrong\u003eHow it works in detail\u003c/strong\u003e\u003c/summary\u003e \u003cp\u003e\n\n```{r details, child=\"details.html\"}\n```\n\n\u003c/p\u003e\u003c/details\u003e\n\n## Features\n\n* Stubbing HTTP requests at low http client lib level\n* Setting and verifying expectations on HTTP requests\n* Matching requests based on method, URI, headers and body\n* Can be used for testing or outside of a testing context\n* Supports async http request mocking with `crul` only\n\n## Supported HTTP libraries\n\n* [crul](https://github.com/ropensci/crul)\n* [httr](https://github.com/r-lib/httr)\n* [httr2](https://github.com/r-lib/httr2)\n\n## Install\n\nfrom cran\n\n```{r eval=FALSE}\ninstall.packages(\"webmockr\")\n```\n\nDev version\n\n```{r eval=FALSE}\n# install.packages(\"pak\")\npak::pak(\"ropensci/webmockr\")\n```\n\n```{r}\nlibrary(webmockr)\n```\n\n## Enable webmockr\n\n```{r}\nwebmockr::enable()\n```\n\n## Inside a test framework\n\n```{r}\nlibrary(crul)\nlibrary(testthat)\n\n# make a stub\nstub_request(\"get\", \"https://httpbin.org/get\") %\u003e%\n  to_return(body = \"success!\", status = 200)\n\n# check that it's in the stub registry\nstub_registry()\n\n# make the request\nz \u003c- crul::HttpClient$new(url = \"https://httpbin.org\")$get(\"get\")\n\n# run tests (nothing returned means it passed)\nexpect_is(z, \"HttpResponse\")\nexpect_equal(z$status_code, 200)\nexpect_equal(z$parse(\"UTF-8\"), \"success!\")\n```\n\n```{r echo=FALSE}\nstub_registry_clear()\n```\n\n\n## Outside a test framework\n\n```{r}\nlibrary(crul)\n```\n\n### Stubbed request based on uri only and with the default response\n\n```{r}\nstub_request(\"get\", \"https://httpbin.org/get\")\n```\n\n```{r}\nx \u003c- HttpClient$new(url = \"https://httpbin.org\")\nx$get('get')\n```\n\nset return objects\n\n```{r}\nstub_request(\"get\", \"https://httpbin.org/get\") %\u003e%\n  wi_th(\n    query = list(hello = \"world\")\n  ) %\u003e%\n  to_return(status = 418)\n```\n\n```{r}\nx$get('get', query = list(hello = \"world\"))\n```\n\n### Stubbing requests based on method, uri and query params\n\n```{r}\nstub_request(\"get\", \"https://httpbin.org/get\") %\u003e%\n  wi_th(\n    query = list(hello = \"world\"),\n    headers = list(\n      'User-Agent' = 'libcurl/7.51.0 r-curl/2.6 crul/0.3.6',\n      'Accept-Encoding' = \"gzip, deflate\"\n    )\n  )\n```\n\n```{r}\nstub_registry()\n```\n\n```{r}\nx \u003c- HttpClient$new(url = \"https://httpbin.org\")\nx$get('get', query = list(hello = \"world\"))\n```\n\n### Stubbing requests and set expectation of a timeout\n\n```{r error=TRUE}\nstub_request(\"post\", \"https://httpbin.org/post\") %\u003e% to_timeout()\nx \u003c- HttpClient$new(url = \"https://httpbin.org\")\nx$post('post')\n```\n\n### Stubbing requests and set HTTP error expectation\n\n```{r error=TRUE}\nlibrary(fauxpas)\nstub_request(\"get\", \"https://httpbin.org/get?a=b\") %\u003e% to_raise(HTTPBadRequest)\nx \u003c- HttpClient$new(url = \"https://httpbin.org\")\nx$get('get', query = list(a = \"b\"))\n```\n\n## httr integration\n\n```{r}\nlibrary(webmockr)\nlibrary(httr)\n\n# turn on httr mocking\nhttr_mock()\n```\n\n```{r eval=FALSE}\n# no stub found\nGET(\"https://httpbin.org/get\")\n#\u003e Error: Real HTTP connections are disabled.\n#\u003e Unregistered request:\n#\u003e   GET https://httpbin.org/get   with headers {Accept: application/json, text/xml, application/xml, */*}\n#\u003e\n#\u003e You can stub this request with the following snippet:\n#\u003e\n#\u003e    stub_request('get', uri = 'https://httpbin.org/get') %\u003e%\n#\u003e      wi_th(\n#\u003e        headers = list('Accept' = 'application/json, text/xml, application/xml, */*')\n#\u003e      )\n#\u003e ============================================================\n```\n\nmake a stub\n\n```{r}\nstub_request('get', uri = 'https://httpbin.org/get') %\u003e%\n  wi_th(\n    headers = list(\n      'Accept' = 'application/json, text/xml, application/xml, */*'\n    )\n  ) %\u003e%\n  to_return(\n    status = 418,\n    body = \"I'm a teapot!!!\",\n    headers = list(im_a = \"teapot\")\n  )\n```\n\nnow returns mocked response\n\n\n```{r eval=FALSE} \n(res \u003c- GET(\"https://httpbin.org/get\"))\nres$status_code\n#\u003e [1] 418\nres$headers\n#\u003e $im_a\n#\u003e [1] \"teapot\"\n```\n\n## httr2 integration\n\n```{r message=FALSE}\nlibrary(webmockr)\nlibrary(httr2)\n\n# turn on httr2 mocking\nenable()\n```\n\n```{r eval=FALSE}\n# no stub found\nreq \u003c- request(\"https://hb.opencpu.org/get\")\nreq_perform(req)\n#\u003e Error: Real HTTP connections are disabled.\n#\u003e Unregistered request:\n#\u003e   GET https://hb.opencpu.org/get\n#\u003e\n#\u003e You can stub this request with the following snippet:\n#\u003e\n#\u003e    stub_request('get', uri = 'https://hb.opencpu.org/get')\n#\u003e ============================================================\n```\n\nmake a stub\n\n```{r}\nstub_request('get', uri = 'https://hb.opencpu.org/get') %\u003e%\n  to_return(\n    status = 418,\n    body = \"I'm a teapot!!!\",\n    headers = list(im_a = \"teapot\")\n  )\n```\n\nnow returns mocked response\n\n\n```{r eval=FALSE} \nreq \u003c- request(\"https://hb.opencpu.org/get\")\nres \u003c- req_perform(req)\nres\nres$status_code\n#\u003e [1] 418\nres$headers\n#\u003e \u003chttr2_headers/list\u003e\n#\u003e im_a: teapot\n```\n\n## Writing to disk\n\nWrite to a file before mocked request\n\n```{r echo=FALSE}\nstub_registry_clear()\nrequest_registry_clear()\n```\n\n```{r}\n## make a temp file\nf \u003c- tempfile(fileext = \".json\")\n## write something to the file\ncat(\"{\\\"hello\\\":\\\"world\\\"}\\n\", file = f)\nreadLines(f)\n## make the stub\ninvisible(\n  stub_request(\"get\", \"https://httpbin.org/get\") %\u003e%\n    to_return(body = file(f))\n)\n## make a request\nout \u003c- HttpClient$new(\"https://httpbin.org/get\")$get(disk = f)\nreadLines(file(f))\n```\n\nOR - you can use `mock_file()` to have `webmockr` handle file and contents\n\n```{r}\ng \u003c- tempfile(fileext = \".json\")\n## make the stub\ninvisible(\n  stub_request(\"get\", \"https://httpbin.org/get\") %\u003e%\n    to_return(body = mock_file(g, \"{\\\"hello\\\":\\\"mars\\\"}\\n\"))\n)\n## make a request\nout \u003c- crul::HttpClient$new(\"https://httpbin.org/get\")$get(disk = g)\nreadLines(out$content)\n```\n\nWriting to disk is supported in `crul`, `httr`, and `httr2`\n\n## Many requests in a row\n\ne.g., many redirects, then a final successful request\n\n```{r eval=FALSE}\nwebmockr::enable()\nlibrary(crul)\nlibrary(fauxpas)\n\nz \u003c- stub_request(\"get\", \"https://httpbin.org/get\")\nto_return(z, status = 200, body = \"foobar\", headers = list(a = 5))\nto_return(z, status = 200, body = \"bears\", headers = list(b = 6))\nto_raise(z, HTTPBadRequest)\nz\n\ncon \u003c- crul::HttpClient$new(url = \"https://httpbin.org\")\n# the first to_return()\nfirst \u003c- con$get(\"get\")\nfirst\nfirst$parse(\"UTF-8\")\n# the second to_return()\nsecond \u003c- con$get(\"get\")\nsecond\nsecond$parse(\"UTF-8\")\n# the third to_return() - fails as specified\nthird \u003c- con$get(\"get\")\n```\n\nNote that subsequent requests past the number of responses given with `to_return()`/etc.\nsimply gives the last response you specified. Although if you set a `to_timeout` or \n`to_raise` this feature won't happen since you fail out.\n\n\n## Contributors\n\n* [Scott Chamberlain](https://github.com/sckott)\n* [Aaron Wolen](https://github.com/aaronwolen)\n\n## Meta\n\n* Please [report any issues or bugs](https://github.com/ropensci/webmockr/issues).\n* License: MIT\n* Get citation information for `webmockr` in R doing `citation(package = 'webmockr')`\n* 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.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fropensci%2Fwebmockr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fropensci%2Fwebmockr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fropensci%2Fwebmockr/lists"}