avatarGavin Fong

Summary

This article discusses the importance of writing test code, specifically unit tests, for Java coding tests and offers tips for writing test code like a professional coder.

Abstract

The article begins by emphasizing the importance of writing test code, explaining that software engineers are responsible for both implementing business functions and writing tests to ensure code logic works accordingly. It then provides a simple coding test example and offers advice for candidates preparing for coding tests, including using JUnit instead of the main function for unit tests, clearly defining test scenarios, setting up mocking if necessary, and using the AssertJ library for assertions. The article concludes by stressing the importance of unit testing for job interview preparation.

Opinions

  • Writing unit tests is an important skill for hands-on software engineers.
  • Unit tests should be written using JUnit instead of the main function.
  • Test scenarios should be clearly defined and organized.
  • Mocking may be necessary for unit tests that involve external components.
  • The AssertJ library is recommended for assertions in unit tests.
  • Unit testing is a crucial skill for job interview preparation.

You will fail Java coding test if you miss this essential skill

How do you make sure your piece of code works according to the requirements?

Photo by Tim Gouw on Unsplash

I interviewed many candidates and tested their coding skills so far and only a few candidates got recommended to the next stage for the position of hands-on software engineer.

Is the coding exercise too challenging? I don’t think so because most candidates were able to solve the problems.

Many candidates failed to answer this question:

How do you make sure your piece of code works according to the requirements?

Sad to say, many potential candidates fail to answer this question. As a result, fail the interview even though it is a demonstration of outstanding problem solving skills.

Many candidates walk through the code line by line and explain how it works. It makes sense, however, it is not the right answer even though the code seems logical.

You are not 100% sure the code logic work fine without testing.

When interviewers ask this question, candidates are in fact expected to write unit test cases instead of explaining the code logic.

Why don’t you just straightforwardly ask the candidate to write unit tests? The question is to check if the candidates have the awareness of code quality.

It is an effective way to check whether the candidates are hands-on software engineers.

Why is writing test code important?

Software engineers are responsible for implementing business functions as well as writing tests that make sure code logic works accordingly.

Before the era of test automation, software engineers complete coding and hand it over to a quality team to perform the testing. Tests are done manually and testers mark down the test results for software engineers to follow up in case of any issues.

In the modern software production line, tests are mostly automated. Software engineers write test codes that verify the system behavior.

Therefore, it is not possible that you don’t write any unit test code if you claim yourself to be a hands-on software engineer.

TDD or not does not matter, you goal is to prove the system logic meets the requirements.

Alright. You know that writing test code is an important skill. How to write test code like a professional coder?

A simple exercise

Let’s take a look at this simple coding test example:

Given an external account balance store which persist the current account balance

Write a function that takes inputs:

  • Transaction (deposit / withdrawal)
  • The current balance

Then, output the updated balance back to the account balance store.

The function should reject invalid transactions (e.g. transaction with negative deposit amount) and transactions that result in negative balance

Assuming that you have done the coding, how do you verify transaction process logic is correct?

Here are my advices to candidates who are preparing for coding tests.

Don’t write unit test using main function

Rule #1 does unit tests in a proper way. Writing unit tests in a main function reveals that you are not used to writing unit tests. Although it is obvious, I observed many candidates attempt to write unit tests in a main function.

JUnit is the de facto when it comes to unit tests in Java. While using JUnit @Test annotation is handy and simple, why bother writing test code in main()? Looking at the method signature, the difference is trivial. However, the use of JUnit @Test allows us to clearly define multiple test scenarios.

Main function

public static void main(String[] args) {
   // … test code …
}

JUnit

@Test
void testTransactionProcess() {
   // … test code …
}

Clearly define test scenarios

It is expected to verify the system logic with test scenarios covering both normal and error cases. Bundling multiple test scenarios into one single test is definitely not a good sign.

Using method name as the scenario description is a common practice. For example,

test<Scenario> pattern

  • testNegativeDeposit()
  • testPositiveDeposit()
  • testPositiveDepositWithNoAccountBalance()

Given-When-Then pattern

  • givenNegativeDeposit_whenProcessTransaction_thenRejectTransaction()
  • givenPositiveDeposit_whenProcessTransaction_thenAccountBalanceUpdated()
  • givenNoAccountBalanceAndPositiveDeposit_whenProcessTransaction_thenAccountBalanceUpdated()

Alternatively, use @DisplayName annotation if you think long method names are too clumsy.

Setup mocking if necessary

It is not common to expect candidates to write unit tests with mocking as part of job interview coding exercise. However, some companies cover it in their coding exercises according to my experience.

Mocking is a common technique that unit tests focus on the target system logic and create stub for external components.

With account balance store as the given external component, unit test mocks the output of getBalance() that returns the mocked value of the current balance. Don’t forget to verify the method call on the mock object if the system logic calls it as part of the output.

Here is the simple skeleton of the mock setup using Mockito library

@ExtendWith(MockitoExtension.class)
public class TransactionProcessorTest {

  @Mock
  private AccountBalanceStore accountBalanceStore;
  
  @InjectMocks
  private TransactionProcessor transactionProcessor;
  
  @Test
  void testPositiveDeposit() {
     String accountNumber = "123";
     BigDecimal currentAccountBalance = BigDecimal.ONE;
     BigDecimal expectedAccountBalance = BigDecimal.TEN;
       
     when(accountBalanceStore.getBalance(accountNumber))
          .thenReturn(currentAccountBalance);
  
       // ... do test on TransactionProcessor …
   
     verify(accountBalanceStore).saveBalance(accountNumber, expectedAccountBalance);
  }
  
}

Use AssertJ library like a pro

The step to verify the system logic output is call assertion in unit tests. Many candidates know that they need to assert the output but they are not familiar with the usage of assertion method calls.

Many candidates struggle with looking for the right method to do the assertion using JUnit and some even use keyword assert in Java language.

To impress the interviewers that you are a hands-on software engineer, I would highly recommend using the AssertJ library.

@Test
void testSimpleDeposit() {
   Transaction deposit = // deposit transaction
   BigDecimal expectedAccountBalance = // expected account balance
  
   TransactionProcessor transactionProcessor = new TransactionProcessor();
   BigDecimal updateBalance = transactionProcessor.handle(deposit);

   // AssertJ assertion
   assertThat(updateBalance).isEqualTo(expectedAccountBalance);
}

Final Thoughts

Unit testing is equally important as system logic coding. Automated unit tests are the efficient and systematic way to verify the system logic. Writing tests would take roughly 40% of total development time. The hands-on skills of writing test code is crucial to a successful software engineer. Therefore, some companies expect candidates to write unit test code as part of a job interview.

Nevertheless, many candidates focus on problem solving skills but ignore the importance of unit testing when they prepare for the coding exercise interview. They fail to get through the coding exercise not because of problem solving skills but their poor performance of unit testing.

Whether you are a hands-on software engineer or not, don’t forget to spend time on practising unit tests for job interview preparation. Here is the list of quick tips:

  • Write unit test in a proper way
  • Clearly organize test scenarios
  • Setup mock if necessary
  • Assert output using fluent method calls
Java
Programming
Software Engineering
Testing
Interview
Recommended from ReadMedium