Mock, Mock. Who’s There? What to Mock in Integration Tests
Integration tests get a bad rep.
Web tests, API tests. Even unit tests. You say it and people get what you mean. But integration tests? Everyone’s got their own interpretation.
Which leaks into how we test them. And what we mock inside.
Mocks. We haven’t talked about that in a while! Should we use them in integration tests? And how?
First, the basics. “Mocking” is a bad word. That’s what the riff-raff do. We are looking for isolation. To explain isolation, we’ll go to the tiniest test of all – the unit test.
Why do we write unit tests? To prove that this little bit of code does what we want.
Take a unit test for a calculator’s add function. It works the same whether the calculator is a mobile app, a web page or an API. The test assumes nothing else out there affects our code. That’s isolation.
And what if we did have a dependency that would impact the behavior? Something we can’t or don’t want to control?
We have two choices. Check them together, or – here it comes – mock the dependency.
When we mock the dependency, we isolate our tested code from the world, and this way, we can go back to our original quest: Our test checks the behavior we’re interested in.
So in other words: We want isolation. We get it by mocking.
Which brings us back to the original question: What should we mock in integration tests?
Let’s say we’re testing an API. Here’s the code.
def get_rate(currency): response = requests.get(RATES_API, params={"from": "USD", "to": currency}, timeout=5) response.raise_for_status() return response.json()["rate"] @app.get("/books/<int:book_id>/price") def book_price(book_id): currency = request.args.get("currency", "USD") book = BOOKS[book_id] rate = get_rate(currency) return jsonify( title=book["title"], price=round(book["price_usd"] * rate, 2), currency=currency, ) As you can see it has a dependency – it calls another API. Should we mock the dependency?
Let’s go back to the goal of the test. If we want to test them together we’d write a test like this:
import bookstore from bookstore import app client = app.test_client() def test_book_price_in_euros_comes_back_from_the_rates_service(): response = client.get("/books/42/price?currency=EUR") assert response.status_code == 200 assert response.json["currency"] == "EUR" assert response.json["price"] > 0 And if we want to test our API in isolation, we’d mock the dependency, like this:
def test_book_price_is_converted_with_the_current_rate(monkeypatch): monkeypatch.setattr(bookstore, "get_rate", lambda currency: 0.5) response = client.get("/books/42/price?currency=EUR") assert response.status_code == 200 assert response.json["price"] == 6.00 The book costs $12, so with a rate of 0.5, we expect 6. See, even the meaning of our test changes in the test name!
It’s really simple: We design the test to check something specific. We then decide if we want to mock the dependency based on the test’s goal.
Now, most of the time, we tend to mock dependencies we don’t own. For example, a 3rd party API. We can’t assume it works the same way every time. Or it’s slow, or expensive. That’s a candidate for mocking.
However, that’s not always true. Sometimes the integration is the point – that’s where the name comes from. It comes down to you deciding what you want the test to tell you.
You know, Gil, you haven’t mentioned AI at all in this post.
So let’s.
AI can generate tests, we know that. And it can generate the tests with the mocks, or without them.
But we just said – we know what we’re looking to check. How will our genie know what we meant? We need to tell it. Maybe we want one or the other. Or both.
But it’s up to us to direct it, otherwise, we’ll get what it chose. Which may not be what we wanted.
So, what should you mock? It doesn’t matter what test you write, you need to design the test to check what you’re interested in. Then write it, mock the things yourself or let the genie do it for you.
Just don’t let AI make a mockery of you.
Originally published at testingil.com.
I'm Gil Zilberfeld. I teach API testing and test automation, and I write about what AI-generated code does to quality.
原文:https://www.a8q9.cn/en/article/mock-mock-who-s-there-what-to-mock-in-integration-tests-28b2de.html