Hero Background

Next-Gen App & Browser Testing Cloud

Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

Next-Gen App & Browser Testing Cloud

What Is Integration Testing in Software Testing?

Integration testing is the level of software testing where individual modules or components are combined and tested as a group to expose defects in their interfaces and interactions. It sits between unit testing (which checks each module alone) and system testing (which checks the whole application). The aim is to catch the bugs that only appear when separately built, already unit-tested pieces start talking to one another — wrong data formats, broken API contracts, incorrect call order, and mismatched assumptions.

In this guide we cover what integration testing is, why it matters, the main approaches (big bang versus incremental top-down, bottom-up, and sandwich), how integration testing compares with unit and system testing, a simple worked example, popular tools, best practices, and the mistakes teams make most often. For an even deeper, example-driven treatment, our complete integration testing guide in the Learning Hub is the companion pillar to this answer.

What Is Integration Testing

Integration testing is the phase of the testing lifecycle where modules that have already passed unit testing are connected and exercised together. A unit test confirms that a single function, class, or component behaves correctly in isolation, usually with its dependencies replaced by mocks. But a real application is a network of modules that exchange data and call one another. Integration testing verifies that those connections — the interfaces — work as designed.

The defects integration testing targets live between components, not inside them. Common examples include a producer module sending a date as a string while the consumer expects a timestamp, an API returning a 200 status with an empty body the caller never anticipated, a database layer returning columns in a different order than the service expects, or two services disagreeing on units (dollars versus cents). Each module can be flawless on its own and the system can still fail at the seams.

An integration test typically involves at least two real modules — replacing mocks with actual collaborators wherever practical — so the data genuinely flows across the boundary you want to validate. The most familiar form is API testing, where you send a real request from one service to another and assert that the response status, schema, and values are correct.

Why Integration Testing Matters

Skipping integration testing is one of the costliest shortcuts a team can take, because interface defects that escape to production are expensive to diagnose and fix. Integration testing earns its place for several reasons:

  • Catches interface defects early. Mismatched data formats, broken contracts, and bad call sequences surface before they reach system testing or users.
  • Validates real data flow. Unit tests use mocks; integration tests use real collaborators, so you confirm the actual data that crosses a boundary, not an idealized stand-in.
  • Reduces risk of system-level failure. Finding a seam defect at the integration stage prevents a cascade of failures later in the lifecycle, when bugs are harder to trace.
  • Supports continuous delivery. Reliable integration suites give teams the confidence to merge and deploy frequently, knowing module boundaries still hold.
  • Documents contracts. Well-written integration tests act as living documentation of how modules are supposed to communicate.

Integration Testing Approaches

There are two broad strategies for combining modules: big bang, where everything is integrated at once, and incremental, where modules are added a few at a time. Incremental approaches split further into top-down, bottom-up, and sandwich (hybrid). To test partially built systems, incremental methods rely on two kinds of dummy modules: stubs and drivers.

  • Stub — a dummy that stands in for a lower-level module that the module under test calls. Used in top-down testing when the called module is not ready yet.
  • Driver — a dummy that calls a lower-level module before its real caller exists. Used in bottom-up testing to invoke a module whose higher-level callers are not built yet.

Big Bang Integration

In big bang integration, you wait until all modules are complete, then combine them in one step and test the whole assembly together. It needs no stubs or drivers, which makes it simple to set up. The downside is severe: when a test fails, the defect could be in any interface, so isolating its root cause is slow and frustrating. Big bang is practical only for very small systems where all modules are ready at the same time.

Top-Down Integration

Top-down integration starts from the highest-level (controlling) modules and works downward through the call hierarchy. Because lower-level modules may not be finished, you replace them with stubs that return canned responses. As real modules become available, stubs are swapped out one by one. The advantage is that the main control flow and high-level design are validated early; the trade-off is that low-level modules are exercised late, and writing realistic stubs takes effort.

Bottom-Up Integration

Bottom-up integration is the mirror image: you begin with the lowest-level utility modules and move upward. Since the higher-level callers may not exist yet, you write drivers that invoke the lower modules and feed them test input. This exercises foundational modules thoroughly and early, which is ideal when the core logic is risky. The drawback is that the top-level user-facing behavior is validated only near the end of integration.

Sandwich (Hybrid) Integration

Sandwich integration, also called hybrid integration, combines top-down and bottom-up. The system is split into three layers; the top layer is tested top-down (with stubs), the bottom layer is tested bottom-up (with drivers), and they meet at the middle target layer. This lets teams work from both ends in parallel and is well suited to large, layered systems. It is the most complex to coordinate and uses both stubs and drivers, so it demands more planning.

System Integration Testing (SIT)

When the "modules" being combined are whole systems or services — for example, an application integrating with a payment gateway, a CRM, and a shipping API — the activity is often called System Integration Testing (SIT). SIT verifies end-to-end data exchange and workflows across independently developed systems, frequently over real network, message-queue, or file-transfer interfaces. It is essentially integration testing scaled up to the system boundary, and it usually runs after component-level integration and before full system testing. See our dedicated guide on what is system integration testing for a deeper look.

Integration vs Unit vs System Testing

Integration testing is one rung on the testing ladder. The list below shows how it differs from the levels immediately around it — unit testing below and system testing above.

  • Scope: Unit testing covers a single module, function, or class; integration testing covers two or more combined modules; system testing covers the complete, integrated application.
  • Goal: Unit testing verifies the internal logic of a unit; integration testing verifies interfaces and data flow between modules; system testing verifies end-to-end behavior against requirements.
  • Dependencies: Unit testing mostly uses mocked or stubbed dependencies; integration testing uses real collaborators where practical; system testing uses a full real environment.
  • Performed by: Unit testing is done by developers; integration testing by developers and testers; system testing by the QA / test team.
  • Typical defects: Unit testing catches logic and boundary errors; integration testing catches interface mismatches and contract breaks; system testing catches functional, workflow, and requirement gaps.

For a deeper side-by-side, see the difference between unit testing and integration testing.

A Simple Example

Imagine an e-commerce app with two modules: an OrderService that creates orders, and a PaymentService that charges the customer. Each passes its own unit tests. An integration test confirms that when OrderService calls PaymentService, the right amount is charged and the correct status flows back. Below is a small Java-style integration test using two real collaborators rather than mocks.

// Integration test: OrderService talking to a real PaymentService
@Test
public void orderIsPaidAndConfirmed() {
    PaymentService payment = new PaymentService();   // real collaborator
    OrderService orders = new OrderService(payment); // wire them together

    Order order = orders.placeOrder("SKU-42", 2, 19.99); // qty 2 @ 19.99

    // The interface between the two modules must agree on the total
    assertEquals(39.98, order.getChargedAmount(), 0.001);
    assertEquals("CONFIRMED", order.getStatus());
    assertTrue(payment.wasCharged(order.getId()));
}

If OrderService sent the price in cents while PaymentService expected dollars, both modules' unit tests would still pass, but this integration test would fail on the charged amount — exactly the kind of seam defect integration testing exists to catch.

Integration Testing Tools

The right tool depends on your stack and the kind of interface you are testing. Common choices include:

  • JUnit / TestNG — Java frameworks that run integration tests alongside unit tests, wiring real collaborators together.
  • Postman, REST Assured, Karate — for API integration testing, sending real HTTP requests across service boundaries and asserting status, schema, and values.
  • Pytest, Mocha / Jest (supertest) — Python and JavaScript runners widely used for service- and route-level integration tests.
  • Testcontainers — spins up real databases, message brokers, and services in Docker so integration tests run against genuine dependencies.
  • Selenium / Appium — when integration extends to the UI, Selenium automation and Appium testing validate that front-end and back-end modules work together in a real browser or device.

For a broader, curated comparison of options across every stack, see our roundup of the top integration testing tools.

Best Practices

  • Prefer incremental over big bang. Adding modules a few at a time keeps each failure traceable to the interface you just connected.
  • Use real collaborators where you can. The whole point is to test the seam, so replace mocks with the actual module or a containerized version of it.
  • Test the contract, not the implementation. Assert on the data shape, status, and values that cross the boundary, not on internal details that may change.
  • Keep tests independent and repeatable. Reset shared state (databases, queues) between runs so one test never depends on another's leftovers.
  • Run them in CI. Wire integration tests into your pipeline so a broken interface fails the build before it can merge.
  • Cover negative paths. Test timeouts, error responses, and malformed payloads, not just the happy path.

Common Mistakes and Troubleshooting

  • Mocking everything. If every dependency is a mock, you are just re-running unit tests. Use at least one real collaborator so the actual interface is exercised.
  • Choosing big bang by default. A single failed assertion in a big-bang run can hide a defect in any of dozens of interfaces. Go incremental to keep failures localized.
  • Flaky tests from shared state. Tests that pass alone but fail together usually share a database row, cache, or queue. Isolate and clean up state between tests.
  • Confusing stubs and drivers. A stub replaces a module you call (top-down); a driver calls a module for you (bottom-up). Mixing them up wastes effort and confuses teammates.
  • Ignoring environment differences. An integration suite that passes on one browser or OS can fail on another due to rendering or platform behavior — validate across real environments.

Cross-Environment Testing With the Cloud

When integration testing reaches the UI layer — confirming the front end, back end, and third-party services all work together — the result can vary by browser, operating system, and device. A flow that integrates perfectly on Chrome for Windows may break on Safari for macOS or on a real Android handset because of rendering, API, or platform quirks.

This is where a cloud grid helps. With TestMu AI, you can run the same integration and end-to-end suites across 3000+ real browser and operating-system combinations on a real device and browser cloud, confirming that integrated modules behave identically everywhere your users are. Pair it with cross browser testing and automation testing to catch environment-specific integration defects before release.

// Run your existing integration/UI suite on the cloud grid
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability("browserName", "Safari");
caps.setCapability("platformName", "macOS Ventura");

WebDriver driver = new RemoteWebDriver(
    new URL("https://USERNAME:[email protected]/wd/hub"), caps);

// The same end-to-end integration flow now runs on Safari for macOS

Conclusion

Integration testing is the level where individually verified modules are combined and tested as a group to expose defects in their interfaces and interactions. Choose an incremental approach — top-down, bottom-up, or sandwich — over big bang so failures stay easy to locate, use stubs and drivers to test partially built systems, exercise real collaborators wherever practical, and validate UI-level integration across real browsers and devices. Get integration testing right and you stop the costly seam defects that unit and system tests alone would miss.

Frequently Asked Questions

What is integration testing in simple terms?

Integration testing is the level of testing where individual, already unit-tested modules are combined and tested together as a group. Its goal is to expose defects in the interfaces between modules — wrong data formats, broken API calls, or mismatched assumptions — that unit tests cannot catch in isolation.

What is the difference between unit testing and integration testing?

Unit testing checks a single module in isolation, usually with mocks. Integration testing combines two or more real modules and verifies they work together across their interfaces. Unit tests find logic bugs inside a unit; integration tests find communication bugs between units, like data-format or contract mismatches.

What are stubs and drivers in integration testing?

A stub is a dummy that stands in for a lower-level module a tested module calls, used in top-down testing. A driver is a dummy that invokes a lower-level module before its callers exist, used in bottom-up testing. Both let you test partially built systems before every real module is ready.

Which integration testing approach is best?

Incremental approaches such as top-down, bottom-up, or sandwich are generally preferred over big bang because they isolate defects to the most recently added interface, making bugs far easier to locate. Big bang is only practical for very small systems where all modules are ready at once.

Is API testing a form of integration testing?

Yes. API testing is one of the most common forms of integration testing because it verifies the contract between two services at their interface. Tools like Postman, REST Assured, and Karate send real requests across module boundaries and assert the responses, status codes, and data shapes match expectations.

Who performs integration testing?

Integration testing is usually a shared responsibility. Developers write and run integration tests for the interfaces between the modules they build, especially in CI, while QA engineers design broader cross-module and system integration scenarios. On many teams the two collaborate so both code-level and end-to-end interface defects are covered.

What is system integration testing (SIT)?

System integration testing (SIT) checks that independently developed systems or services — such as an app, a payment gateway, and a CRM — exchange data and workflows correctly across their real interfaces. It is integration testing at the system boundary, typically run after component integration and before full system testing.

Related Questions

Test Your Website on 3000+ Browsers

Get 100 minutes of automation test minutes FREE!!

Test Now...

KaneAI - Testing Assistant

World’s first AI-Native E2E testing agent.

...

TestMu AI forEnterprise

Get access to solutions built on Enterprise
grade security, privacy, & compliance

  • Advanced access controls
  • Advanced data retention rules
  • Advanced Local Testing
  • Premium Support options
  • Early access to beta features
  • Private Slack Channel
  • Unlimited Manual Accessibility DevTools Tests