### Question:
TrackActor extends TransportingActor<Track> implements TileableListener { @Override public void ballAccepted(Tileable tileable, Direction direction, Marble marble) { MarbleActor actor = (MarbleActor) getContext().actor(marble); Vector2 origin = stageToLocalCoordinates(actor.localToStageCoordinates( new Vector2(actor.getWidth() / 2.f, actor.getHeight() / 2.f))); prepareActor(actor, direction, origin); if (getTileable().passesMidpoint(direction, marble)) { travelAnimation(actor, direction, origin); } else { bounceTravelAnimation(actor, direction, origin); } addActorBefore(modifier, actor); } TrackActor(Track tileable, ActorContext context); @Override void ballAccepted(Tileable tileable, Direction direction, Marble marble);  }### Answer:
@Test public void testFilterJoker() throws Exception { assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue(); latch = new CountDownLatch(2); Marble marble = new Marble(MarbleType.JOKER); JokerMarbleActor jokerActor = new JokerMarbleActor(marble, context); jokerActor.addActor(new Actor()); context.register(marble, jokerActor); FilterTrack track = (FilterTrack) grid.get(0, 1).getTileable(); TrackActor actor = (TrackActor) context.actor(track); Direction direction = Direction.TOP; TileableListener listener = spy(new TileableListener() { @Override public void ballReleased(Tileable tileable, Direction direction, Marble marble) { latch.countDown(); } }); track.addListener(listener); app.postRunnable(() -> { actor.addActor(context.actor(marble)); track.accept(direction, marble); latch.countDown(); }); assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue(); Thread.sleep(200); verify(listener, atLeastOnce()).ballAccepted(any(), eq(direction), any()); verify(listener, atLeastOnce()).ballReleased(any(), eq(direction.inverse()), any()); }