Package: unmock
Unmock(Python SDK)Public API mocking for Python.Unmock can be used to test modules that perform requests to third-party
APIs like Hubspot, SendGrid, Behance, and hundreds of other public APIs.Unmock can also be used to mock these APIs in a development environment,
i.e. an express server on a local machine or in a staging environment.The Unmock Python package offers intuitive, hassle-free SDK to the
Unmock service with minimal setup steps.The ultimate goal of unmock is to provide a semantically and
functionally adequate mock of the internet.Unmock also provides access via other languages, all with similar
interface. We haveunmock-jsalready publicly available, and we are working on .Net, PHP and Java.
We're open to more requests - justlet us know!Table of ContentsUnmockHow does it work?InstallUsageTestsDevelopmentunmock.ioScopingSaving mocksIgnoring aspects of a mockAdding a signatureWhitelisting APIunmock.io tokensContributingLicenseHow does it work?Unmock works by overriding Python's low-levelHTTPConnection's andHTTPRequest's functions, thereby capturing calls
made by popular packages such asrequestsandurllib3.Unmock works out of the box for most APIs that it mocks and does not
require any additional configuration. For APIs that it does not mock
yet, or to tweak return values from the unmock service, you can consult
the URLs printed to the command line by unmock.We intend to offer Python2.7 support quite soon, along with other common
libraries such asaiohttp,pycurl, etc.Install$pipinstallunmockUsageTestsIn your unit tests, you can invoke unmock in several ways:If you're using pytest for your tests, you can either use the unmock
fixture (you don't even need to import unmock!) -importpytestimportrequestsdeftest_behance(unmock_local):response=requests.get("https://www.behance.net/v2/projects/5456?api_key=u_n_m_o_c_k_200")assertresponse.json().get("project").get("id")==5456... or you may want to use unmock for all your tests, in which case you
can simply use the--unmockflag for pytest:pytesttests--unmockYou can control use unmock in a scoped manner using context managers:# do stuff
with unmock.patch():
    response = requests.get("https://www.example.com/")
# do stuff with mocked response
real_response = requests.get("https://www.example.com/")  # won't be mocked

# You can also access the returned object to modify certain runtime behaviour:
with unmock.patch() as opts:
    # can modify certain behaviour aspects via `opts` object now too
    response = requests.get("https://www.example.com/")You can have fine grained control over unmock using theinitandresetmethods, and modify theUnmockOptionsobject during runtime:importunmock# do stuffopts=unmock.init()res1=requests.get("https://www.example.com")# will be mockedopts.save=Trueres2=requests.get("https://www.example.com")# will be mocked and response will be savedunmock.reset()res3=requests.get("https://www.example.com")# will not be mockedUnmock will then either serve JIT semantically functionally correct
mocks from its database or an empty JSON object for unmocked APIs that
can be filled in by the user. The address of these editable objects is
printed to the command line during tests.DevelopmentAfter you create your flask, django, or own server, callunmock_options=unmock.init()unmock_options.ignore("story")# equivalent to calling:unmock.init(ignore="story")This has the same effect as activating unmock in your tests.
It will intercept HTTP traffic and serve semantically and functionally
adequate mocks of the APIs in the unmock catalogue.
The main difference is the result ofignore("story")passed to unmock
options, which tells the service to ignore the order of mocked requests.
Always use this option when the order of mocked data does not matter,
i.e. when you are in sandbox or development mode.
For users of theunmock.ioservice, this will
help unmock better organize your mocks in its web dashboard.unmock.ioThe URLs printed to the command line are hosted by unmock.io. You can
consult the documentation about that servicehere.ScopingAs a handy shortcut to initializing and reseting the capturing of API
calls, we also offer the use of context manager viaunmock.patch().patchaccepts as parameters anything thatinitaccepts.Saving mocksAll mocks can be saved to a folder called.unmockin your user's home
directory by adding asavefield to the unmock options object like so:unmock_options=unmock.init(save=True)You can also specify a specific location to save the directory:unmock_options=unmock.init(save=True,path=".")# Saves in current pathUnmock refers to every mock by a unique hash. Individual mocks or groups
of mocks can be saved by setting save to either a single hash or an
array of hashes like so:unmock_options=unmock.init(save=["ahash","anotherhash","yetanotherhash"])Ignoring aspects of a mockSometimes, you would like for two mocks of slightly API calls to be
treated as equivalent by unmock. For example, you may want allGETcalls to the same path with different headers to be served the same
mock. To do this, use theignorefield of the unmock options object.
You can do this while initializing unmock or afterwards (as shown before
with ignoring"story"):# Option A:unmock_options=unmock.init()unmock_options.ignore("headers","story")# Option B:unmock.init(ignore=["headers","story"])The following fields may be ignored:headers: the headers of the requesthostname: the hostname of the requestmethod: the method of the request (ie GET, POST, PUT, DELETE).
Note that this iscase insensitive!path: the path of the requeststory: the story of the request, meaning its order in a series of requestsIgnore evaluates regular expressions, so you can also pass"headers|path"instead of["headers", "path"]. Furthermore, to
ignore nested headers, pass a dictionary such as{"headers": "Authorization" }, or to match against the value of a
header,{"headers": { Authorization: "Bearer *" }}. When using the
ignoremethodon theUnmockOptionsobject (returned from a call toinit),
you may pass either a list (*args) or a dictionary (**kwargs).Adding a signatureSometimes, it is useful to sign a mock with a unique signature. This is
useful, for example, when AB testing code that should serve two
different mocks for the same endpoint in otherwise similar conditions.
To do this, use thesignaturefield of the unmock options object:unmock_options=unmock.init()unmock_options.signature="signature-for-this-particular-test"# Equivalent tounmock.init(signature="signature-for-this-particular-test")Whitelisting APIIf you do not want a particular API to be mocked, whitelist it.unmock_options=unmock.init()unmock_options.whitelist=["api.hubspot.com","api.typeform.com"]# Equivalent to:unmock.init(whitelist=["api.hubspot.com","api.typeform.com"])unmock.io tokensIf you are subscribed to theunmock.ioservice,
you can pass your unmock token directly to the unmock object.unmock.init(token="my-token")At a certain point this becomes a bit tedious, (even if very readable),
at which point you will want to create a credentials file. Seeunmock.io/docsfor more information on
credential files.
Behind the scenes, we automatically create a credentials file for you,
for caching purposes. With this, subsequent calls tounmock.init()will read the token from the credential files.ContributingThanks for wanting to contribute! We will soon have a contributing page
detaling how to contribute. Meanwhile, star this repository, open issues
and ask for more features and support!Please note that this project is released with aContributor Code of Conduct. By participating in
this project you agree to abide by its terms.LicenseMITCopyright (c) 2018–2019Meeshkanand othercontributors.