google / ExoPlayer

This project is deprecated and stale. The latest ExoPlayer code is available in https://github.com/androidx/media
https://developer.android.com/media/media3/exoplayer
Apache License 2.0
21.7k stars 6.02k forks source link

How to simulate ExoPlayer in unit tests ? #6328

Closed thibseisel closed 4 years ago

thibseisel commented 5 years ago

[REQUIRED] Searched documentation and issues

[REQUIRED] Question

I am using ExoPlayer to play audio with a background service controlled via a Media Session. Since I am doing TDD, I'd like to cover most code with unit and integration tests. I have an ExoPlayer instance that is injected into my service components with Dagger 2, so that any class that communicates with the player has it as a constructor parameter.

Here is my question : how should I mock/fake ExoPlayer, so that I can test components that use it in isolation ? I know that ExoPlayer is an interface and therefore can be mocked with any mocking framework but this only works for simple interactions and mocking Player.EventListener callbacks is rather hard. For that purpose, something like a FakeExoPlayer seems more appropriate.

What I need is a FakeExoPlayer, or a SimpleExoPlayer with fake components that:

Here are some things I thought of to solve the question:

Big thanks in advance.

marcbaechinger commented 5 years ago

We are having a bunch of such tests in ExoPlayerTest.

It uses the ExoPlayerTestRunner from thes testutil module you are mentioning above. The test runner internally creates a TestExoPlayer which extends from SimpleExoPlayer.

The test ExoPlayer instance can be wired up with various FakeXYZ components.

To trigger events you can set up a ActionSchedule (see ExoPlayerTest for examples) which issues call to the ExoPlayer instance. Your test asserts can then verify whether a given state has been changed or whether expected methods have been called.

tonihei commented 5 years ago

The general approach should be as Marc described above. Please have a look at our ExoPlayerTestRunner/ExoPlayerTest/ActionSchedule classes to see how this can be done.

More specific comments:

dispatches Player.EventListener events immediately on the test thread,

This approach is using a real player. So all events are dispatched exactly the same way as in non-test cases.

reacts to changes to a ConcatenatedMediaSource

There is no issue with using ConcatenatingMediaSource in a testing scenario or such a test runner.

prepares real media sources, but does not actually fetch and play them

That one is not that easy to solve. We usually use some kind of FakeMediaSource or FakeAdaptiveMediaSource for test purposes. Using actual media sources is problematic because they expect actual media data to work correctly. You can use the real media source If you can provide actual data in the test. Then you could inject a custom DataSource that emits this data and everything should work fine.

marcbaechinger commented 4 years ago

Closing due to lack of activity.