How to test Combine code in Swift

Learn how you can test your Combine code by using expectations

Bruno Lorenzo
3 min readMay 2, 2023

Testing our code is a fundamental part of the development process.

But, if we're using the Combine framework, this could be unintuitive at first sight. That doesn't mean that it can't be done. We just need to dig into some more advanced concepts that Swift provides us.

Let's take a look at how we can easily include unit tests in our Combine code.

Photo by Christina @ wocintechchat.com on Unsplash

Let’s start by looking at the following manager that simulates handling a traffic light.

From our initial Combine article we know that by adding @Published wrapper, we get a free Publisher that we can access by using the $ character.

Testing

Before we dig into how to actually test Combine code, let’s review some core concepts regarding unit testing. We can summarize it in three steps.

  • Step 1: Define what you want to test.
  • Step 2: Execute the operation you want to test with the value you defined in Step 1.
  • Step 3: Evaluate the result that you got from Step 2.

Take a look at the following example:

This is a very simple example so you can understand the concept. We first defined our expected value for the test, a red light. Then, we call an operation that changes the current light value to red. And finally, we make sure that the current light’s value is the same as the expected one.

This is fine, but what should we do if we want to test simulateFlow function? You can notice that inside that function we are changing the light property three times. So, at the end of the function's execution, the property's value should change from green to yellow, from yellow to red, and finally from red to green.

As you can imagine, in order to test the function, we need to make sure that the property’s value, has the right value at the end, but most importantly we must be sure that all the value changes (from one to another) are correct.

Expectations

XCTestExpectations are a type of object that Apple provides to us for testing asynchronous code. Basically, you create an expectation at the beginning of your test and when certain conditions are met you fulfill that expectation. The test’s execution will wait until the expectation is fulfilled or when a timeout is expired.

So, in order to test our function, we will need to wait until we collect all the expected values that we know currentLightproperty should change. Then, we will fulfill the expectation if we got all the values. Otherwise, the test will fail because of the timeout.

With this in mind, we now have the right tool to create a new test for our simulateFlow function

Let’s breakdown the code:

Step 1

  • We create a new expectation to use in our test.
  • We defined the expected values that we know the property should change at some point.
  • We also created a new empty list that we are going to use to store the values that we’ll receive from the Publisher.

Step 2

  • We start listening to the Publisher’s values.
  • We call the function so we start receiving the property’s value changes.

Step 3

  • We wait for the expectation to be fulfilled or for the timeout to be reached.
  • We evaluate if the received values that we got are correct.

Conclusion

Testing Combine code is pretty easy once you understand the potential of expectations. Although we saw a very short and simple example, you can use this same technique for testing more complex solutions.

For instance, you can apply these principles to test your ViewModel’s states in an MVVM architecture, or to test some mocking network calls.

Have any questions? Feel free to drop me a message! 🙂

  • 🤓 Join me on Twitter for regular content on iOS development tips and insights
  • 🚀 Check out my GitHub where I share all my example projects

--

--

Bruno Lorenzo
Bruno Lorenzo

Written by Bruno Lorenzo

Software Engineer | Innovation Manager at www.houlak.com | Former iOS Tech Lead | I write about iOS, tech, and producitivy

No responses yet