Unit Tests

Testing custom operators

RxSwift uses RxTests for all operator tests, located in the AllTests-* target inside the project Rx.xcworkspace.

This is an example of a typical RxSwift operator unit test:

  1. func testMap_Range() {
  2. // Initializes test scheduler.
  3. // Test scheduler implements virtual time that is
  4. // detached from local machine clock.
  5. // This enables running the simulation as fast as possible
  6. // and proving that all events have been handled.
  7. let scheduler = TestScheduler(initialClock: 0)
  8. // Creates a mock hot observable sequence.
  9. // The sequence will emit events at desginated
  10. // times, no matter if there are observers subscribed or not.
  11. // (that's what hot means).
  12. // This observable sequence will also record all subscriptions
  13. // made during its lifetime (`subscriptions` property).
  14. let xs = scheduler.createHotObservable([
  15. next(150, 1), // first argument is virtual time, second argument is element value
  16. next(210, 0),
  17. next(220, 1),
  18. next(230, 2),
  19. next(240, 4),
  20. completed(300) // virtual time when completed is sent
  21. ])
  22. // `start` method will by default:
  23. // * Run the simulation and record all events
  24. // using observer referenced by `res`.
  25. // * Subscribe at virtual time 200
  26. // * Dispose subscription at virtual time 1000
  27. let res = scheduler.start { xs.map { $0 * 2 } }
  28. let correctMessages = [
  29. next(210, 0 * 2),
  30. next(220, 1 * 2),
  31. next(230, 2 * 2),
  32. next(240, 4 * 2),
  33. completed(300)
  34. ]
  35. let correctSubscriptions = [
  36. Subscription(200, 300)
  37. ]
  38. XCTAssertEqual(res.events, correctMessages)
  39. XCTAssertEqual(xs.subscriptions, correctSubscriptions)
  40. }

Testing operator compositions (view models, components)

Examples of how to test operator compositions are contained inside Rx.xcworkspace > RxExample-iOSTests target.

It’s easy to define RxTests extensions so you can write your tests in a readable way. Provided examples inside RxExample-iOSTests are just suggestions on how you can write those extensions, but there are a lot of possibilities on how to write those tests.

  1. // expected events and test data
  2. let (
  3. usernameEvents,
  4. passwordEvents,
  5. repeatedPasswordEvents,
  6. loginTapEvents,
  7. expectedValidatedUsernameEvents,
  8. expectedSignupEnabledEvents
  9. ) = (
  10. scheduler.parseEventsAndTimes("e---u1----u2-----u3-----------------", values: stringValues).first!,
  11. scheduler.parseEventsAndTimes("e----------------------p1-----------", values: stringValues).first!,
  12. scheduler.parseEventsAndTimes("e---------------------------p2---p1-", values: stringValues).first!,
  13. scheduler.parseEventsAndTimes("------------------------------------", values: events).first!,
  14. scheduler.parseEventsAndTimes("e---v--f--v--f---v--o----------------", values: validations).first!,
  15. scheduler.parseEventsAndTimes("f--------------------------------t---", values: booleans).first!
  16. )

Integration tests

It is also possible to write integration tests by using RxBlocking operators.

Importing operators from RxBlocking library will enable blocking the current thread and wait for sequence results.

  1. let result = try fetchResource(location)
  2. .toBlocking()
  3. .toArray()
  4. XCTAssertEqual(result, expectedResult)