Test of RxJava concurrency

Source: Internet
Author: User

When developing the software, we need to make sure that the code executes correctly. To get quick feedback on each modification, developers typically use custom tests.

There is not much difference between testing in synchronous Rx and unit testing in normal Java. If you want to test asynchronous code, there may be a bit of attention to it, such as testing the following code:

Observable.interval(1, TimeUnit.SECONDS)    .take(5)

The above Observable emits a stream of data, which takes 5 seconds to launch all of the data. If we use automation to test this code, does that mean that the test code is going to be executed for 5 seconds, and if we have thousands of such tests, the test will take a lot of time to complete.

Testscheduler

The code for the example above, 5 seconds of time is actually mostly waiting. If we can speed up the system clock, we can quickly complete the transmission of the data stream. Although the system clock cannot be accelerated during the actual operation, a virtual clock can be accelerated. In the Rx design, consider the use of time-related operations only in scheduler. This can be used to replace the real Scheduler with a virtual testscheduler.

Testscheduler is the same as the thread scheduling feature described in the previous section. The scheduled task is either executed immediately or at some point in the future. The difference is that the time in the Testscheduler is not moving, only the time that is called will continue.

Advancetimeto

The Advancetimeto function is to forward the clock in the Testscheduler to the specified timescale.

Testscheduler s = schedulers. Test();S. Createworker(). Schedule(() System. out. println("Immediate"));S. Createworker(). Schedule(() System. out. println("20s"), -, Timeunit. SECONDS);S. Createworker(). Schedule(() System. out. println("40s"), +, Timeunit. SECONDS);System. out. println("Advancing to 1ms");S. Advancetimeto(1, Timeunit. MILLISECONDS);System. out. println("Virtual Time:"+ S. Now());System. out. println("Advancing to 10s");S. Advancetimeto(Ten, Timeunit. SECONDS);System. out. println("Virtual Time:"+ S. Now());System. out. println("Advancing to 40s");S. Advancetimeto( +, Timeunit. SECONDS);System. out. println("Virtual Time:"+ S. Now());

Results:

to1time1to10time10000to40s20s40time40000

The 3 tasks created in the above example, the first task executes immediately, and the second and third are executed in the future. You can see that if you do not call Advancetimeto to make time go forward, all tasks will not execute because time is stopped in Testscheduler. When time goes on, Testscheduler will perform all tasks that meet the time criteria synchronously.

Advancetimeto can be set at any time. You can also go back to the past (set the time earlier than the current time). Therefore, this function may cause unforeseen bugs if it is not paid attention to. It is generally recommended to use the following function.

Advancetimeby

Advancetimeby, as the name implies, advances much on the current time basis.

Testscheduler s = schedulers. Test();S. Createworker(). Schedule(() System. out. println("Immediate"));S. Createworker(). Schedule(() System. out. println("20s"), -, Timeunit. SECONDS);S. Createworker(). Schedule(() System. out. println("40s"), +, Timeunit. SECONDS);System. out. println("Advancing by 1ms");S. Advancetimeby(1, Timeunit. MILLISECONDS);System. out. println("Virtual Time:"+ S. Now());System. out. println("Advancing by 10s");S. Advancetimeby(Ten, Timeunit. SECONDS);System. out. println("Virtual Time:"+ S. Now());System. out. println("Advancing by 40s");S. Advancetimeby( +, Timeunit. SECONDS);System. out. println("Virtual Time:"+ S. Now());

Results:

by1time1by10time10001by40s20s40time50001
Triggeractions

Triggeractions does not modify the time. It is used only to perform tasks that are currently scheduled.

Testscheduler s = schedulers. Test();S. Createworker(). Schedule(() System. out. println("Immediate"));S. Createworker(). Schedule(() System. out. println("20s"), -, Timeunit. SECONDS);S. Triggeractions();System. out. println("Virtual Time:"+ S. Now());

Results:

time0
scheduling conflicts

Some tasks may be performed at the same time. If this happens, it is called a dispatch conflict. The order in which these tasks are dispatched is the order in which they are executed (that is, executed sequentially)

Testscheduler s = schedulers. Test();S. Createworker(). Schedule(() System. out. println("First"), -, Timeunit. SECONDS);S. Createworker(). Schedule(() System. out. println("Second"), -, Timeunit. SECONDS);S. Createworker(). Schedule(() System. out. println("Third"), -, Timeunit. SECONDS);S. Advancetimeto( -, Timeunit. SECONDS);

Results:

FirstSecondThird
Test

Most of the operation functions of the Rx observable have an overloaded form that can specify Scheduler. Testscheduler can also be used on these functions.

@Testpublic void Test () {Testscheduler Scheduler = new Testscheduler ();List<long> expected = Arrays. Aslist(0L1L2L3L4L;list<long> result = new Arraylist<> ();Observable. Interval(1, Timeunit. SECONDS, scheduler). Take(5). Subscribe(I-Result. Add(i));Asserttrue (Result. IsEmpty());Scheduler. Advancetimeby(5, Timeunit. SECONDS);Asserttrue (Result. Equals(expected));}

This allows the test code to be completed very well and is suitable for testing short Rx code. In the actual code, you can encapsulate the function that gets Scheduler, use Testscheduler in the debug version, and use the real Scheduler in the release version.

Testsubscriber

In the above tests, we manually collected the emitted data and compared it to the expected data to determine whether the test was successful. Because such tests are common, Rx provides a testsubscriber to help simplify the testing process. The preceding test code uses Testsubscriber to change to this:

@Testpublic void Test () {Testscheduler Scheduler = new Testscheduler ();testsubscriber<long> subscriber = new testsubscriber<> ();List<long> expected = Arrays. Aslist(0L1L2L3L4L;Observable. Interval(1, Timeunit. SECONDS, scheduler). Take(5). Subscribe(subscriber);Asserttrue (subscriber. Getonnextevents(). IsEmpty());Scheduler. Advancetimeby(5, Timeunit. SECONDS);Subscriber. Assertreceivedonnext(expected);}

Testsubscriber not only collects data, but also some of the following functions:

java.lang.Thread getLastSeenThread()java.util.List<Notification<T>> getOnCompletedEvents()java.util.List<java.lang.Throwable> getOnErrorEvents()java.util.List<T> getOnNextEvents()

There are two points that require additional attention:

    1. The Getlastseenthread function. Testsubscriber checks the execution of the callback function on that thread and logs the last thread. You can use this function if you want to test whether the callback function occurs in the GUI thread.
    2. Interestingly, Getoncompletedevents can return multiple end events. This is a violation of the Rx agreement, which can be checked by testing.

Testsubscriber also provides a number of common judgment functions:

void assertNoErrors()void assertReceivedOnNext(java.util.List<T> items)void assertTerminalEvent()void assertUnsubscribed()

You can also block until a specific event occurs:

void awaitTerminalEvent()void awaitTerminalEvent(long timeout, java.util.concurrent.TimeUnit unit)void awaitTerminalEventAndUnsubscribeOnTimeout(long timeout, java.util.concurrent.TimeUnit unit)

Specifying a time may cause an exception to be timed out (not completed within the specified time).

This article is from the cloud in the Thousand peaks http://blog.chengyunfeng.com/?p=979

Test of RxJava concurrency

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.