iOS Swift: Unit Testing Combine Publisher

Saad El Oulladi
3 min readOct 20, 2023

iOS development has undergone significant changes since the introduction of SwiftUI and Combine. Reactive programming has become a standard practice, as Combine is included in the iOS SDK by default.

Unit testing reactive code can sometimes be challenging, as the inputs and outputs are not easily obtained as in the case of imperative programming.

The boring approach

The most common way to test a Combine publisher is to create an expectation and fulfill it once the value is received, as shown below:

While using expectations to test a Combine publisher is intuitive, it comes with some drawbacks:

  1. It involves writing a lot of code, for what is supposed to be a relatively simple test case.
  2. When an expected value is not received, having an expectation with a timeout means waiting for the expectation to fail, which can increase the overall execution time of unit tests, potentially leading to longer test durations.
  3. The use of expectations with timeouts may force us to adjust the timeout value, making the test pass in cases where ideally shouldn’t introduce any unnecessary delays.

In other words, the above example works, but it’s evident that there’s room for improvement.

The alternative

Here, we’re utilizing a different approach, and it’s clear that the test code is significantly simpler and more concise.

Of course, this is made possible by using a small helper that we’ll discuss in detail below.

We’ve introduced a spy method for the Combine Publisher, which returns a spy object. Importantly, we don't retrieve the publisher's values…