vendredi 22 septembre 2017

Integration test an API whose behavior depends on the current time

I have a few APIs I'm trying to thoroughly integration test -- I'm hitting the service which it's running in a test environment, I can't just use dependency injection to solve all my problems. We already have a good suite of unit tests on these classes.

The API I'm testing is SaveThingy. It saves a Thingy if it's valid, and returns you the id of it. One of the checks is that you can only save a thingy at certain times, say only on weekdays. If you call SaveThingy on the weekend, it insults you personally instead of saving a Thingy. The implementation looks something like the following

ThingyId saveThingy(Thingy thingy) {
    if (isWeekend(LocalDate.now().getDayOfWeek())) {
        throw new PersonalInsultException("your mother wears army boots");
    }
    return thingyDao.save(thingy);
}

I'd ideally like to have both cases tested each time we run integration tests, without any waiting. In some code, I want tests similar to the following to run each time.

@Test
public void saveThingy_validThingyOnWeekday_savesThingy() {
    ThingyId id = serviceUnderTest.saveThingy(THINGY);
    assertThat(serviceUnderTest.getThingyById(id)).isEqualTo(THINGY);
}

@Test(expected = PersonalInsultException.class)
public void saveThingy_validThingyOnWeekend_receivePersonalInsult() {
    serviceUnderTest.saveThing(THINGY);
}

Are there any standard ways that allow complete testing of such APIs? I've considered a few options (below), but wanted to get additional opinions.

  1. say no to integration testing, live with only unit tests for these APIs
  2. change the remote clock, either using a private API or by literally ssh-ing into the host before running each test
  3. write tests that are time dependent; only testing one of the possible behaviors, or testing one behavior then sleeping until other conditions are met
  4. invent dummy data that will always save or always throw an exception

Aucun commentaire:

Enregistrer un commentaire