0

I'm relatively new to FastApi and unit testing in Python.

I am testing an api that has a conditional check on whether an environment variable FOO is present.

I am trying to clear that environment variable so that when the api gets invoked by the test the environment variable is not found:

  def test_invoice(self, requests_mock):
     with mock.patch.dict(os.environ, {}, clear=True):          
        
        url = "/api/invoices/check"

        requests_mock.post(url, real_http=True)

        response = self.test_client.post(url, json.dumps([invoice_id]))

  @router.post("/api/invoices/check")
  def invoices_api():
    if os.environ.get("FOO"):

When the test client gets invoked and the env var is checked the env variable is not None?

How I can make the code I am trying to test use the mocked os environment?

Note: I've also tried clearing the env variable with the following syntax:

  @mock.patch.dict(os.environ, {}, clear=True)
  def test_invoice(self, requests_mock):
Vinyl Warmth
  • 2,226
  • 3
  • 25
  • 50
  • Are you trying to clear it for just the test or for the whole app? – drum Nov 05 '22 at 20:11
  • I want it cleared in the api I'm trying to test. Will update my question to make that clearer – Vinyl Warmth Nov 05 '22 at 20:18
  • Does the API run in another process? In that case patching `os.environ` won't do any good. – MB-F Nov 05 '22 at 20:30
  • Perhaps it is, I'm not sure. I think I need to move the `os.environ` call out of the api and pass the value as configuration. I know exactly how to do this in .NET but not clear in Python... – Vinyl Warmth Nov 05 '22 at 20:33
  • Does the module which consumes the var use `var = os.environ.get("VAR")` or similar at module scope? This includes use as a default argument in a function. In that case you are too late to patch `os.environ`, and need to patch in the module namespace. – wim Nov 05 '22 at 20:40
  • I think I see what you mean. I can abstract the `os.environ` call to a function and patch the function call? – Vinyl Warmth Nov 05 '22 at 22:11
  • I added working example of what you are trying to achieve. Feel free to add more details into your question so I could adapt the answer more into your specific case. – kosciej16 Nov 06 '22 at 09:55

1 Answers1

0

It's a working example how it could be done.

# app.py
import os

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def invoices_api():
    if os.environ.get("FOO"):
        return 1
# test_me.py
import os
from unittest.mock import patch

from fastapi.testclient import TestClient

from app import app

client = TestClient(app)

class TestMe:
    def setup_method(self):
        os.environ["FOO"] = "A"

    def test_1(self):
        resp = client.get("/")
        assert resp.json() == 1

    def test_2(self):
        with patch.dict(os.environ, clear=True):
            resp = client.get("/")
            assert resp.json() is None

    def test_3(self):
        resp = client.get("/")
        assert resp.json() == 1
kosciej16
  • 6,294
  • 1
  • 18
  • 29