Junit : Best Practices

In the previous topics we learn about the unit testing by Junit and implementation of Test Cases by using Junit 5. In this topic we will learn about the some Junit Best Practices and Why it’s required.

Why JUnit Best Practice Needed?

When writing Junit test case, we need to ensure the following points:

  • Test cases should be easily readable
  • Test cases should be extremely consistent and reliable
  • It should indicate the real issues in the production code
  • Tests should fail only when there is a bug in the system
  • It will be good if more test cases executed frequently
  • All the test cases should execute very fast

You can achieve all these Junit features when apply the “Junit Best Practices” when writing the Junit Test cases.

See Also:

What is the Junit Best Practices for Test Case writing?

These are some high-level points that’s need to keep in mind while writing the test cases for an application or project.

  • Test cases should be readable.
  • The name of the test class and test methods should be descriptive.
  • Develop the JUnit test cases in a way that it should execute faster.
  • Always first plan unit tests for functionalities that have fewer dependencies.
  • Plan for proper tests for all functionalities.
  • Don’t use test case constructor to setup test cases.
  • Avoid skipping test cases with the usage of @Disabled without any reason, a reason could also be passed for @Disabled for any developer to know why a particular test case was is skipped.
  • Each unit test method should have only one assertion.
  • Maintain proper order of parameters in assertions.
  • Practice the resilient assertions.
  • Make each test independent of all others.
  • Don’t go for unit-testing of any settings or configuration.
  • Confirm that unit test code is parted from production code.
  • Do not print anything out in unit tests.
  • Avoid the usage of static members inside the test class, if you have used then re-initialize on each test case.
  • Do not give your own exception that occurs only to fail a test.
  • Don’t write testcases for configuration settings.
  • Plan to run the test cases completely in-memory, avoid doing a test for availing file system and DB, and for HTTP requests, Use mocking Junit framework like Mockito etc. for external or third-party dependency.
  • Implement Code Coverage tools like Cobertura, JACOCO etc. with your project so that verify that written Junit Test cases covering complete code. As per industry standard code coverage ratio should configure as 80%.
  • Integrate test cases with build script(ant or maven or gradle) so that all Junit test case will execute before your application ready for deploy.
  • Capture the results using XML formatter so that make test case report readable with color text.

Note: While writing test case assume these test cases will not execute in sequence so never try to use one test case result on another test case.

Good Tips for Junit Test Cases Writing

Here are some good tips for Junit Test Cases Writing that will guide when writing the test cases for any method in class.

  • Write descriptive name of your test case
TestCreateUser_NullUserId_ShouldThrowException
TestCreateUser_DuplicateUserId_ShouldThrowException
TestCreateUser_ValidUserId_Should_Pass
  • When writing test cases for method arguments then check for each parameters of method for null and these methods should return Invalid parameter exception if any parameter is null.
  • After null unit test implementation write test for functional unit.
  • Each test case should have only one assertion and it should cover one functional condition of code. Like if-else, switch, loops, exception etc.
  • For some methods where need to meet SLA of time or dependent of third-party API result write test cases for @Timeout.
// Timeout after 3 nanoseconds
@Timeout(value = 3, unit = TimeUnit.NANOSECONDS) 
@Test
void annotationDelayInValidTest() throws InterruptedException {
		obj.delay(2); // Delay for 2 seconds
}

JUnit 4

@Test(expected=ArithmeticException.class)
public void testCalculatorDivide()
{
assert(5, obj.devide(5,0))
}

JUnit 5

@Test
void testCalculatorDivide() {
Exception exception = assertThrows(ArithmeticException.class, () -> cobj.division(5, 0));
assertEquals("divide by zero", exception.getMessage());
	}
  • If need to test particular test case for multiple parameter values then write test case as @ParameterizedTest
@ParameterizedTest
	@NullAndEmptySource
	@ValueSource(blankStrings = { " ", "   ", "\t", "\n" })
	void checkText(String sampleText) {
	    assertTrue(sampleText == null || sampleText.trim().isEmpty());
	}

  • Use @Before and @After or @BeforeAll or @AfterAll test method for Initialization and close the dependencies of test method.
  • Use Mocking Junit framework for testing external service or DB related methods.
  • Don’t write test cases for configuration and constant related classes.
  • Ensure tests that are time dependent so that test data will not consider as expired data.
  • Use local when using date and time while implementing test cases.
  • Keeps your test cases on test packages in same project so that maintain easily and skip also in case required.

Summary

No doubt writing Junit increase the code quality of the code and by following the best practices reduce the maintenance and execution time of test. If you keep above points in mind that will help you to write good quality of test cases and make your application reliable and reduce the regression testing time with less defects in your code.

Let me know your views for Junit implementation and Junit Best Practices for writing Unit test cases for your code.