Liam SY Kim
by Liam SY Kim
2 min read

Categories

It is the post which I studied for high coverage of test code in company.

Why do we need TestCode?

Before knowing how to test RxSwift based code, I wonder the reason why should we write test code.

  • Good for maintainance
  • predefined requirement which make intended programming posiible
  • Because we have test code, Do not need to consider side effect error when we refactor codes.

These are the advantages of test code which I agreed from others posting.

Therefore, We can code intented as requirement, and don’t need to worry about error from refactoring 😆

It is hard to write test code at first, but it gives more advantage for a long time.

Personally, I used to write code with RxSwift, I wonder How do I test RxSwift based code?.

The answer is Test the code whether Observable comes in to Observer as we want!

TestCode in RxSwift

For testing RxSwift code, I will explain the concept of RxTest and RxBlocking, and then, show you the example of them for understanding.

This posting is for knowing basic usage of Testing RxSwift, not for adapting RxTest to project.

For overall, the difference between RxTest and RxBlocking is like below.

Defference RxBlocking
RxTest
Observable Cold
Hot & Cold
Time tracking No
Yes

In summary, RxBlocking is for cold observable which could emits onComplete, and it cannot detect the emitting time of events as well.

However, RxTest can be used in Hot Observables where the stream does not break without onComplete, and it is also possible to check whether the Observable has arrived at the desired timing.

You don’t need to understand all yet, I will explain the detail with example below.☺️

RxBlocking

RxBlocking converts the previously received events into an array when the Observer receives the onComplete event from the Observable.

That’s why it cannot be used in hot observables where onComplete does not come in.

Let’s look at this with the code.

func testOfRxBlocking() {
	let observable = Observable.from(["apple", "orange", "banana"]).toBlocking()
	let fruits = try! observable.Array()
	XCTAssertEqual(fruits, ["apple", "orange", "banana"])
}

As you can see, there are toBlocking() and .Array() for all to understand RxBlocking.

  • toBlocking() : Observable -> BlockingObservable

  • Array(): BlockingObservable -> Array

BlockingObservable which is made by toBlocking makes the emitted events to be an Array.

RxTimeInterval

If you put the timeout factor, you can also receive events up to the time you want.

toBlocking(timeout: RxTimeInterval?)

In this case, Hot Observable also can uses RxBlocking as exception.

RxTest

RxTest creates a test scheduler, and then creates observers and observables within the test scheduler.

By input the time and value in event .next() at the same time, when the input time is specified by the developer, the event is emitted to the observer.

Let’s see the below for understanding :)

func testOfRxTest() {
	let scheduler = TestScheduler(initialClock: 0)
	let bag = DisposeBag()
	
	let observable = scheduler.createHotObservable([
		.next(1, "apple"),
		.next(2, "orange"),
		.next(3, "banana")
	])
	
	let observer = scheduler.createObserver(String.self)
	observable.subscribe(observer).disposed(by: bag)
	
	scheduler.start()
	
	XCTAssertEqual(observer.events, [
		.next(1, "apple"),
		.next(2, "orange"),
		.next(3, "banana")
	])
}

The order is ,

1. Create TestScheduler.

2. Define observable and obserber from TestScheduler

3. Running Test Scheduler through .start ()

4. Check if observer.events came in the same value as sent

Additionally, Scheduler runs until the last time given in .next (). Forthermore, onComplete comes in, it continues until onComplete comes in.

As a result, we can test both Hot Observable and Cold Observable!

Conclusion

It is difficult at first, but for good maintainance of our projet, why don’t you adapt RxTest on your project?

Reference