Do I unit test for logging in the tests for methods that produced said logging?

by KeizerHarm   Last Updated October 14, 2019 20:26 PM - source

I've read a couple answers on this very site regarding multiple asserts in a unit test. The general idea I get is that it's okay to test a single response body for multiple conditions and use more than one assert for that: the key is that a unit test should only fail for one reason.

Here I have a test method (for a login rest resource) using that logic:

@Test
void loginReturnsCorrectResponse() {
    var response = resource.login(TEST_GOOD_LOGIN_REQUEST);
    var entity = response.getEntity();
    assertTrue(entity instanceof LoginResponse);
    assertFalse(((LoginResponse) entity).getToken().isBlank());
}

With the same logic I've split distributed this test over two test methods:

@Test
void loginWithEmptyUserReturnsBadRequest() {
    LoginRequest requestWithEmptyUser = new LoginRequest("", TEST_GOOD_PASSWORD);
    var response = resource.login(requestWithEmptyUser);
    assertEquals(400, response.getStatus());
}

@Test
void loginWithEmptyPassReturnsBadRequest() {
    LoginRequest requestWithEmptyPassword = new LoginRequest(TEST_GOOD_USER, "");
    var response = resource.login(requestWithEmptyPassword);
    assertEquals(400, response.getStatus());
}

Now I'm at a loss how to handle tests for logs. Do I fold them in with these methods, since they are a result of the same action?

(here myLogFile is a testing file that's cleared again before every test)

@Test
void loginReturnsCorrectResponse() {
    var response = resource.login(TEST_GOOD_LOGIN_REQUEST);
    var entity = response.getEntity();
    assertTrue(entity instanceof LoginResponse);
    assertFalse(((LoginResponse) entity).getToken().isBlank());

    assertTrue(myLogFile.containsError(Level.INFO, "Login successful"));
}

@Test
void loginWithEmptyUserReturnsBadRequest() {
    LoginRequest requestWithEmptyUser = new LoginRequest("", TEST_GOOD_PASSWORD);
    var response = resource.login(requestWithEmptyUser);
    assertEquals(400, response.getStatus());

    assertTrue(myLogFile.containsError(Level.INFO, "Bad login request"));
}

Etc. They are still technically testing that the same thing happened, but the issue is that there's now two ways this could fail: either the thing being tested has failed, or the logging handler has failed.

Instead I could put all the logging in separate methods; but since I log pretty much everything, this would effectively duplicate my amount of unit tests.

A third way I can devise is to not test that specific things got logged, but instead test the logging handler itself for all levels in a separate test. I don't know if that's ideal either.

Which is preferable here?



Related Questions


How to hide logs in some tests but not in others?

Updated January 17, 2019 02:26 AM

Get all logging output with mock

Updated January 07, 2018 11:26 AM