Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to simulate ExoPlayer in unit tests ? #6328

Closed
thibseisel opened this issue Aug 21, 2019 · 3 comments
Closed

How to simulate ExoPlayer in unit tests ? #6328

thibseisel opened this issue Aug 21, 2019 · 3 comments
Assignees
Labels

Comments

@thibseisel
Copy link

[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:

  • prepares real media sources, but does not actually fetch and play them,
  • dispatches Player.EventListener events immediately on the test thread,
  • reacts to changes to a ConcatenatedMediaSource.

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

  • Create my own fake implementation of ExoPlayer, dispatching Player.EventListener events to observers myself in prepare, seekTo, setPlayWhenReady methods. That's a lot of work and it's not ensured to have the same behavior as a real ExoPlayer implementation (don't mock classes you don't own !).
  • Use fake components from testutils projects. While those components looks really helpful in testing ExoPlayer itself, I struggle to find how to use them for my use case, i.e. simulating ExoPlayer behavior to test an external component.
  • By injecting a fake DataSource.Factory, I'd be able to produce fake MediaSources to feed the ConcatenatingMediaSource created in player preparation code. I think the new Playlist API described in Top level playlist API for ExoPlayer #6161 should make it easier to test media playlist use cases.

Big thanks in advance.

@marcbaechinger
Copy link
Contributor

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
Copy link
Collaborator

tonihei commented Sep 5, 2019

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
Copy link
Contributor

Closing due to lack of activity.

@google google locked and limited conversation to collaborators Dec 28, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants