Unit testing retrofit RxJava

Unit testing retrofit RxJava

ReactiveX is a combination of the best ideas from the Observer pattern, the Iterator pattern, and functional programming.

RxAndroid is an extension to RxJava. It providers a scheduler to run code in the main thread of Android. It also provides the ability to create a scheduler that runs on a Android handler class. With this schedulers, you can define an observable which does its work in a background thread, and post our results to the main thread. This allows for example to replace a AsyncTask implementations which RxJava.

The subscriber observes in the main thread
Observable is called outside the main thread

To manage RxJava is not so difficult, When we have to use RxJava in Unit test, We need to create these element:

1. BaseSchedulerProvider (Father)
2. ImmediateSchedulerProvider (Testing)
3. SchedulerProvider (Application)

Android Test, Unit testing retrofit RxJava
You can check my complete example in GitHub

BaseSchedulerProvider :

public interface BaseSchedulerProvider {

    @NonNull
    Scheduler computation();

    @NonNull
    Scheduler io();

    @NonNull
    Scheduler ui();
}

ImmediateSchedulerProvider I use for a test:

public class ImmediateSchedulerProvider implements BaseSchedulerProvider {

    @NonNull
    @Override
    public Scheduler computation() {
        return Schedulers.immediate();
    }

    @NonNull
    @Override
    public Scheduler io() {
        return Schedulers.immediate();
    }

    @NonNull
    @Override
    public Scheduler ui() {
        return Schedulers.immediate();
    }
}

And SchedulerProvider I use in my Presenter

public class SchedulerProvider implements BaseSchedulerProvider {

    // Prevent direct instantiation.
    public SchedulerProvider() {
    }

    @Override
    @NonNull
    public Scheduler computation() {
        return Schedulers.computation();
    }

    @Override
    @NonNull
    public Scheduler io() {
        return Schedulers.io();
    }

    @Override
    @NonNull
    public Scheduler ui() {
        return AndroidSchedulers.mainThread();
    }
}

In my PresenterTest I setUp like this:

public class TopicPresenterTest {

            @Mock
            private RemoteDataSource mRemoteDataSource;

            @Mock
            private TopicContract.View mView;

            private BaseSchedulerProvider mSchedulerProvider;

            TopicPresenter mPresenter;

            List<Topics> mList;

            @Before
            public void setup() {
            MockitoAnnotations.initMocks(this);

                    Topics topics = new Topics(1, "Discern The Beach");
                    Topics topicsTwo = new Topics(2, "Discern The Football Player");
                    mList = new ArrayList<>();
                    mList.add(topics);
                    mList.add(topicsTwo);
//ADD IMMEDIATESCHEDULERPROVIDER !!!!!!!!!!!!!!!
                    mSchedulerProvider = new 
                    ImmediateSchedulerProvider();

                    mPresenter = new TopicPresenter(mRemoteDataSource, mView, mSchedulerProvider);

            }

            @Test
            public void fetchData() {

                when(mRemoteDataSource.getTopicsRx())
                        .thenReturn(rx.Observable.just(mList));

                mThemePresenter.fetch();

                InOrder inOrder = Mockito.inOrder(mView);
                inOrder.verify(mView).setLoadingIndicator(false);
                inOrder.verify(mView).showTopics(mList);

            }

}

And In my Presenter I call to my server with retrofit:

public class TopicPresenter {

    @NonNull
    private BaseSchedulerProvider mSchedulerProvider;

    public TopicPresenter(@NonNull RemoteDataSource remoteDataSource, @NonNull TopicContract.View view) {
                    this.mRemoteDataSource = checkNotNull(remoteDataSource, "remoteDataSource");
                    this.mView = checkNotNull(view, "view cannot be null!");
                    this.mSchedulerProvider = new SchedulerProvider();
 //ADD COMPOSITESUBSCRITPTION !!!!!!     
                    mSubscriptions = new CompositeSubscription();

                    mView.setPresenter(this);
    }

    @Override
    public void fetch() {

        Subscription subscription = mRemoteDataSource.getTopicsRx()
                .subscribeOn(mSchedulerProvider.computation())
                .observeOn(mSchedulerProvider.ui())
                .subscribe((List<Topics> listTopics) -> {
                            mView.setLoadingIndicator(false);
                            mView.showTopics(listTopics);
                        },
                        (Throwable error) -> {
                            try {
                                mView.showError();
                            } catch (Throwable t) {
                                throw new IllegalThreadStateException();
                            }

                        },
                        () -> {
                        });

        mSubscriptions.add(subscription);
    }

    @Override
    public void subscribe() {
        fetch();
    }

    @Override
    public void unSubscribe() {
        mSubscriptions.clear();
    }


}

You can check my complete example in GitHub

PHPUnit tips

Hopefully, all this phpunit tips can help you to test your own applications. If you have any questions, or suggestions, feel free to contact me!Some people have asked me to write something about testing, so I’ve decided to make this post and share some phpunit tips that I’ve learn.

This is not meant to be another tutorial of how to start writing your own tests with phpunit. Well, actually it is, but the purpose of my post is to explain you how to deal with real scenarios. If you try to search for phpunit examples, most places will show you how to create very simple test cases, but I haven’t seen many places explaining how to do more complex things. That’s exactly the purpose of this article. Moreover, If you think something’s missing, I encourage you to ask me about it, and I’ll try to append it to the post, or if it’s a big enough subject, I’ll create a whole new article about it.

Let’s begin from a very simple case, and we’ll get into something a bit more complicated step by step.
I assume that you already know what’s PHPUnit, and some basic concepts of how to use it, like for instance the dataproviders or mocks. If you think that you need some help to get started, have a look at PHPUnit’s official page and feel free to ask me, if needed.

Happy case in PHPUnit: Imagine you have an isolated class and you wanna test some of its methods.


/**
 * This code has been taken just as an example, from: http://snipplr.com/view.php?codeview&id=9024
 */
 class TheDeveloperWorldIsYours {
public static function generateUrlFromText($strText) {
 $strText = preg_replace('/[^A-Za-z0-9-]/', ' ', $strText);
 $strText = preg_replace('/ +/', ' ', $strText);
 $strText = trim($strText);
 $strText = str_replace(' ', '-', $strText);
 $strText = preg_replace('/-+/', '-', $strText);
 $strText = strtolower($strText);
 return $strText;
}
}

How would you test that? This might be an attempt:

/**
 * TheDeveloperWorldIsYours_Test
 *
 * @uses PHPUnit_Framework_TestCase
 */
class TheDeveloperWorldIsYours_Test extends PHPUnit_Framework_TestCase {

    public function setUp() {
    }

    protected static $inputs = array(
        array('   string    with  many   spaces   ', 'string-with-many-spaces'),
        array('stríng wïth wêird Àccents', 'str-ng-w-th-w-ird-ccents'),
        array('$peci4l: ch%r·ct3r$.', 'peci4l-ch-r-ct3r'),
        array('nice-string', 'nice-string'),
        array('testing+with+phpunit-is-cool', 'testing-with-phpunit-is-cool')
    );

    public static function providerFormat()
    {
        return self::$inputs;
    }

    /**
     * testFormat
     * Ensure that the string is being properly cleaned
     *
     * @dataProvider providerFormat
     * @param mixed $input
     * @param mixed $result
     * @access public
     * @return void
     */
    public function testFormat($input, $result) {
        $this->assertEquals($result, TheDeveloperWorldIsYours::generateUrlFromText($input));
    }
}

I assume that you have already set up some boostrap that takes care of including the required files (in this case, we just need to include the file where the class TheDeveloperWorldIsYours before executing the test).
If you run the test file with PHPUnit, you’ll notice that all the tests are passing, and you might want to add some corner cases to feel more comfortable, such as very long strings, empty strings, numbers and so. However, that’s out of the scope of this post (I could create a whole article about it). Nobody would know better than you the casuistic of your application, and you are the one responsible to add all the missing tests in each case.

So, in this example, we have the best scenario: The method is public, and even static, so we don’t need to instantiate the class in order to test the method. Also, the class doesn’t inherits from any other class, so we don’t have to worry about including all the required files.

Now, let’s assume we had the following scenario:

 class TheDeveloperWorldIsYours extends Some_Parent_Class {
protected function generateUrlFromText($strText) {
 $strText = preg_replace('/[^A-Za-z0-9-]/', ' ', $strText);
 $strText = preg_replace('/ +/', ' ', $strText);
 $strText = trim($strText);
 $strText = str_replace(' ', '-', $strText);
 $strText = preg_replace('/-+/', '-', $strText);
 $strText = strtolower($strText);
 if($strText === '') {
    die('Unable to generate a valid url from the given input');
 }
 return $strText;
}
}

Continue reading