@SuppressWarnings({"unchecked", "rawtypes"})
  @Test
  public void skipsIdenticalScrobble() throws InterruptedException, ApplicationException {

    // a second scrobble of the same track is just silently thrown away.
    // verify by checking that it's the original scrobble (check startTime)
    // that remains in the queue when a dupe is scrobbled.

    Scrobble scrobble1 = new Scrobble(user1, track1, false);
    Thread.sleep(3);
    Scrobble scrobble2 = new Scrobble(user1, track1, false);

    Message message1 = new GenericMessage<Scrobble>(scrobble1);
    Message message2 = new GenericMessage<Scrobble>(scrobble2);
    PollableChannel scrobbleChannel = mock(PollableChannel.class);
    when(scrobbleChannel.receive()).thenReturn(message1, message2, null);

    scrobbleService.setScrobbleChannel(scrobbleChannel);
    scrobbleService.receive();

    assertNotNull(scrobbleService.userScrobbles);
    assertEquals(1, scrobbleService.userScrobbles.keySet().size());
    assertEquals(1, scrobbleService.userScrobbles.get(scrobble1.getLastFmUser()).size());
    assertEquals(
        scrobble1.getStartTime(),
        scrobbleService.userScrobbles.get(scrobble1.getLastFmUser()).getFirst().getStartTime());
  }
  @SuppressWarnings({"unchecked", "rawtypes"})
  @Test
  public void scrobblerIgnoresTooNewSubmissions() throws ApplicationException {

    Scrobble scrobble = new Scrobble(user1, track1, false);

    Message message = new GenericMessage<Scrobble>(scrobble);
    PollableChannel scrobbleChannel = mock(PollableChannel.class);
    when(scrobbleChannel.receive()).thenReturn(message, (Message) null);

    scrobbleService.setScrobbleChannel(scrobbleChannel);
    scrobbleService.receive();

    scrobbleService.scrobbleTracks();
    assertNotNull(scrobbleService.userScrobbles);
    assertEquals(1, scrobbleService.userScrobbles.keySet().size());
    assertEquals(1, scrobbleService.userScrobbles.get(scrobble.getLastFmUser()).size());

    scrobble.setStartTime(scrobble.getStartTime().minusSeconds(10));
    scrobbleService.scrobbleTracks();
    assertEquals(1, scrobbleService.userScrobbles.get(scrobble.getLastFmUser()).size());

    scrobble.setStartTime(scrobble.getStartTime().minusMinutes(10));
    scrobbleService.scrobbleTracks();
    assertEquals(0, scrobbleService.userScrobbles.get(scrobble.getLastFmUser()).size());
  }
  @SuppressWarnings({"unchecked", "rawtypes"})
  @Test
  public void differentUsersCanScrobbleSameTrack() throws ApplicationException {

    Scrobble scrobble1 = new Scrobble(user1, track1, false);
    Scrobble scrobble2 = new Scrobble(user2, track1, false);

    Message message1 = new GenericMessage<Scrobble>(scrobble1);
    Message message2 = new GenericMessage<Scrobble>(scrobble2);
    PollableChannel scrobbleChannel = mock(PollableChannel.class);
    when(scrobbleChannel.receive()).thenReturn(message1, message2, null);

    scrobbleService.setScrobbleChannel(scrobbleChannel);
    scrobbleService.receive();

    assertNotNull(scrobbleService.userScrobbles);
    assertEquals(2, scrobbleService.userScrobbles.keySet().size());
    assertEquals(1, scrobbleService.userScrobbles.get(scrobble1.getLastFmUser()).size());
    assertEquals(1, scrobbleService.userScrobbles.get(scrobble2.getLastFmUser()).size());
  }
  @SuppressWarnings({"unchecked", "rawtypes"})
  @Test
  public void previousScrobbleGetsRemovedOnImmediateOtherScrobble()
      throws InterruptedException, ApplicationException {

    // differently from test case above, a close subsequent scan of a
    // new track removes the previous scrobble from the queue (not the new).

    Scrobble scrobble1 = new Scrobble(user1, track1, false);
    Thread.sleep(3);
    Scrobble scrobble2 = new Scrobble(user1, track2, false);

    assertFalse(scrobble1.getStartTime().equals(scrobble2.getStartTime()));

    Message message1 = new GenericMessage<Scrobble>(scrobble1);
    Message message2 = new GenericMessage<Scrobble>(scrobble2);
    PollableChannel scrobbleChannel = mock(PollableChannel.class);
    when(scrobbleChannel.receive()).thenReturn(message1, message2, null);

    scrobbleService.setScrobbleChannel(scrobbleChannel);
    scrobbleService.receive();

    assertNotNull(scrobbleService.userScrobbles);
    assertEquals(1, scrobbleService.userScrobbles.keySet().size());
    assertEquals(1, scrobbleService.userScrobbles.get(scrobble1.getLastFmUser()).size());
    assertEquals(
        track2Id,
        scrobbleService.userScrobbles.get(scrobble1.getLastFmUser()).getFirst().getTrack().getId());
  }