Apyflux Logo

Apyflux

Menu

Unit Testing in API Development | Test Controllers & Business Logic Effectively

Discover how to perform unit testing in API development. Learn to test controllers, business logic, and write reliable API tests using tools like Jest, Pytest, and MockMvc. Best practices and real examples included.

Introduction

As the demand for Application Programming Interfaces (APIs) are increasing in the current digital world, it's become the backbone of every software application.

Whether you're building microservices, mobile backends, or web apps, well-tested APIs are crucial for reliability and scalability. That’s where unit testing comes in.

Unit testing plays a critical role in API development by ensuring that each small part of your code works as expected. From validating a user input to handling business workflows, it helps developers catch bugs early and build confidence in the codebase.

While testing is essential at all levels, it's especially important to cover both controllers and business logic — the brain and the face of your API. But wait, how is unit testing different from other types of testing?

Let’s quickly break it down:

  • Unit testing focuses on individual pieces of code (functions, methods).
  • Integration testing checks how different modules work together.
  • End-to-end (E2E) testing simulates real user scenarios across the entire application.

Each layer has its role, but unit testing is the foundation. In this blog we have explained everything about Unit Testing in API development. Read this blog till the last paragraphs, to understand it.

What is Unit Testing in API Development?

Unit testing means writing tests for small, isolated units of your code — typically functions or methods. In API development, this includes things like utility functions, service logic, and even controller methods (when isolated properly).

The goal?

To ensure that each unit of the code performs as expected — without relying on external systems like databases or third-party services.

Benefits of unit testing:

  • Fast feedback during development
  • Reliable and maintainable code
  • Easier debugging when something breaks

Common tools:

  • JavaScript: Jest, Mocha
  • Python: Pytest
  • Java: JUnit

These tools provide frameworks to write, organize, and run your tests efficiently.

Unit Testing API Controllers

Controllers are the entry points for your API. They handle incoming requests, call the appropriate business logic, and return responses. That makes unit testing API controllers essential.

What should you test in controllers?

  • Response status codes (200, 400, 500, etc.)
  • Proper delegation to service layers
  • Input validation (e.g., missing fields, incorrect types)

Mocking is key

Since controllers often call external services or databases, you’ll want to mock these dependencies. This isolates the controller's logic and prevents flakiness in your tests.

Example tools:

  • Node.js: Supertest, Jest (with mocks)
  • Java: MockMvc
  • Python: unittest.mock

Sample scenario:

Let’s say you have a GET /users/:id controller:

  • Test that it returns 200 with valid ID.
  • Test that it returns 404 if user not found.
  • Test that it calls the correct service method.

These unit tests ensure your controller handles the request properly and gracefully fails when needed.

How to Unit Test Business Logic

Now comes the core — business logic. This includes anything that involves rules, workflows, calculations, or decisions that your API performs.

Examples:

  • Calculating discounts
  • Validating user permissions
  • Sending notifications

It’s crucial to separate business logic from controllers and move it into service or helper classes. This makes it easier to test and reuse.

When possible, write pure functions — functions without side effects. These are the easiest to test and the most predictable.

Real example:


function calculateDiscount(amount, isPremiumUser) {
  if (isPremiumUser) return amount * 0.9;
  return amount;
}

This function is easy to test in isolation and has no dependencies. That's what good unit tests thrive on.

Writing Business Test Logics for APIs

Let’s get practical. Here’s how to approach writing business test logics for APIs:

1. Set up your test files and suites

  • Keep them in a tests/ directory or use naming conventions like *.spec.js.

2. Write meaningful and independent test cases

  • Each test should focus on one thing. Use descriptive names.

3. Use assertions and mock data

  • Feed realistic input and check output using assertions.

4. Test edge cases and failure paths Example: What happens if input is null? What if the user is unauthorized?

5. Avoid over-mocking While mocking is useful, don’t mock everything. Always test the actual logic.

6. Test asynchronous logic Use async/await or promises correctly. Always test both success and failure scenarios.

Mocking, Stubbing, and Dependency Injection

When it comes to unit testing, mocking is your best friend. It helps you isolate the unit under test by faking the behavior of its dependencies.

Why mock?

  • To prevent real DB or API calls
  • To simulate edge cases
  • To test only the current unit

Popular mocking libraries:

  • JavaScript: Sinon.js, Jest mocks
  • Python: unittest.mock
  • Java: Mockito

You can mock:

  • Database calls
  • External APIs
  • Middleware (like auth checks)

Use dependency injection to make your code more testable. Instead of creating services inside functions, inject them from the outside so you can replace them with mocks during testing.

Real-World Example: Unit Testing a Node.js API

Let’s look at a real example using Node.js, Jest, and Supertest.

Controller:


app.get('/discount/:userId', async (req, res) => {
  const discount = await discountService.calculate(req.params.userId);
  res.status(200).json({ discount });
});

Service:


async function calculate(userId) {
  const user = await getUserFromDB(userId);
  return user.isPremium ? 20 : 10;
}

Test:


test('GET /discount returns correct discount', async () => {
  const mockService = { calculate: jest.fn().mockResolvedValue(20) };
  const res = await request(app).get('/discount/123');
  expect(res.status).toBe(200);
  expect(res.body.discount).toBe(20);
});

Output:

Jest shows which lines are covered and gives you a coverage summary. This is gold for improving test completeness.

Best Practices for Unit Testing APIs

Here are some tips to keep your unit tests healthy:

  • Keep tests fast and isolated
  • Write descriptive test names
  • Maintain separation of unit vs integration tests
  • Use CI pipelines to run tests automatically
  • Regularly refactor tests along with code changes
  • Always test edge cases and failure paths
  • Don’t skip testing async or error-handling logic

Well-tested code is a safety net, not a burden. It saves time and stress in the long run.

Conclusion

Unit testing is more than just a checkbox — it's an investment in the health of your API. By testing both controllers and business logic, you ensure that your API behaves predictably and reliably.

Whether you're unit testing API controllers, exploring how to unit test business logic, or writing business test logics for APIs, remember: small, isolated tests lead to big wins in stability and maintainability.

Adopt a test-driven or at least a test-first mindset, and your future self (and your team) will thank you. In the end, well-tested APIs aren’t just cleaner — they’re faster, safer, and built to scale.

Written By
Published on
Sanjeev
Apr 21, 2025
Share Article

Related APIs

Apyflux Logo

Apyflux

Unleashing the potential by connecting developers to a world of powerful APIs.
Secured Payments By
RazorPay Logo
  • Visa_Logo
  • Mastercard_Logo
  • Amex_Logo
  • Maestro_Logo
  • Rupay_Logo
  • UPI_Logo_Small
© 2025 Apyflux. All rights reserved.

Hi there!

Let's help you find right APIs!