Unit testing: Is it a good practice to have assertions in setup methods?

avandeursen picture avandeursen · Sep 3, 2009 · Viewed 9.6k times · Source

In unit testing, the setup method is used to create the objects needed for testing.

In those setup methods, I like using assertions: I know what values I want to see in those objects, and I like to document that knowledge via an assertion.

In a recent post on unit tests calling other unit tests here on stackoverflow, the general feeling seems to be that unit tests should not call other tests: The answer to that question seems to be that you should refactor your setup, so that test cases do not depend on each other.

But there isn't much difference in a "setup-with-asserts" and a unit test calling other unit tests.

Hence my question: Is it good practice to have assertions in setup methods?

EDIT:

The answer turns out to be: this is not a good practice in general. If the setup results need to be tested, it is recommended to add a separate test method with the assertions (the answer I ticked); for documenting intent, consider using Java asserts.

Answer

KLE picture KLE · Sep 3, 2009

Instead of assertions in the setup to check the result, I used a simple test (a test method along the others, but positionned as first test method).

I have seen several advantages:

  • The setup keeps short and focused, for readability.
  • The assertions are run only once, which is more efficient.

Usage and discussion :

For example, I name the method testSetup().

To use it, when I have some test errors in that class, I know that if testSetup() has an error, I don't need to bother with the other errors, I need to fix this one first.

If someone is bothered by this, and wants to make this dependency explicit, the testSetup() could be called in the setup() method. But I don't think it matters. My point is that, in JUnit, you can already have something similar in the rest of your tests:

  1. some tests that test local code,
  2. and some tests that is calls more global code, which indirectly calls the same code as the previous test.

When you read the test result where both fail, you already have to take care of this dependency that is not in the test, but in the code being called. You have to fix the simple test first, and then rerun the global test to see if it still fails. This is the reason why I'm not bothered by the implicit dependency I explained before.