In banking software or financial software, validation of an account number is a mandatory scenario. In this article, as a sample let us take a valid account number
- To contain only 14 digits
- All 14 digits cannot be zeros
- The account number cannot be null or cannot be empty.
With this let us prepare a maven project to have this business logic in 3 different methods and its corresponding JUnit test cases.
Example Maven Project
Project Structure:
This is a maven project.
pom.xml
XML
<? xml version = "1.0" encoding = "UTF-8" ?> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 < modelVersion >4.0.0</ modelVersion > < groupId >com.gfg.BankAccountNumberServices</ groupId > < artifactId >BankAccountNumberServices</ artifactId > < packaging >jar</ packaging > < version >1.0-SNAPSHOT</ version > < properties > < project.build.sourceEncoding >UTF-8</ project.build.sourceEncoding > < maven.compiler.source >1.8</ maven.compiler.source > < maven.compiler.target >1.8</ maven.compiler.target > < junit.version >5.3.1</ junit.version > < pitest.version >1.4.3</ pitest.version > </ properties > < dependencies > <!-- junit 5, unit test --> < dependency > < groupId >org.junit.jupiter</ groupId > < artifactId >junit-jupiter-engine</ artifactId > < version >${junit.version}</ version > < scope >test</ scope > </ dependency > </ dependencies > < build > < finalName >maven-mutation-testing</ finalName > < plugins > < plugin > < groupId >org.apache.maven.plugins</ groupId > < artifactId >maven-surefire-plugin</ artifactId > < version >3.0.0-M1</ version > </ plugin > < plugin > < groupId >org.pitest</ groupId > < artifactId >pitest-maven</ artifactId > < version >${pitest.version}</ version > < executions > < execution > < id >pit-report</ id > < phase >test</ phase > < goals > < goal >mutationCoverage</ goal > </ goals > </ execution > </ executions > <!-- Need this to support JUnit 5 --> < dependencies > < dependency > < groupId >org.pitest</ groupId > < artifactId >pitest-junit5-plugin</ artifactId > < version >0.8</ version > </ dependency > </ dependencies > < configuration > < targetClasses > < param >com.gfg.BankAccountNumberServices.*BankAccountNumberServices*</ param > </ targetClasses > < targetTests > < param >com.gfg.BankAccountNumberServices.*</ param > </ targetTests > </ configuration > </ plugin > </ plugins > </ build > </ project > |
Business Logic:
- Method 1: Validation Using Long.parseLong
- Method 2: Validation Using Character.isDigit
- Method 3: Using Regular Expression
BankAccountNumberServices.java
Java
import java.util.regex.Matcher; import java.util.regex.Pattern; public class BankAccountNumberServices { // Lets assume that bank account number should be with // 14 digits (numeric) only It cannot contain 14 zeros, // it cannot be null, cannot be empty These are initial // level of validations, other than that for checking // whether valid unique number then bank database has to // be checked and there we need to check But in this // tutorial let us check only with initial level of // validations public boolean isValidAccountNumberMethod1(String accountNumber) { if (accountNumber == null || accountNumber.equalsIgnoreCase( "" )) { return false ; // should be a valid number and it // cannot be null or "" } try { Long.parseLong( accountNumber); // As account number is of // 14 digits, we need to go // with Long.parseLong only if (accountNumber.length() == 14 ) { int count = 0 ; for ( int i = 0 ; i < accountNumber.length(); i++) { if (accountNumber.charAt(i) == '0' ) { count += 1 ; } } if (count == 14 ) { // all digits are 0 return false ; } else { return true ; } } else { return false ; } } catch (NumberFormatException e) { return false ; } } public boolean isValidAccountNumberMethod2(String accountNumber) { if (accountNumber == null || accountNumber.equalsIgnoreCase( "" )) { return false ; // should be a valid number and it // cannot be null or "" } if (accountNumber.length() == 14 ) { int count = 0 ; for ( int i = 0 ; i < accountNumber.length(); i++) { // If we find the character is not a digit, // then it has to be returned false if (!Character.isDigit( accountNumber.charAt(i))) { return false ; } if (accountNumber.charAt(i) == '0' ) { count += 1 ; } } if (count == 14 ) { // all digits are 0 return false ; } else { return true ; } } else { return false ; } } public boolean isValidAccountNumberUsingRegularExpression( String accountNumber) { if (accountNumber == null || accountNumber.equalsIgnoreCase( "" )) { return false ; // should be a valid number and it // cannot be null or "" } if (accountNumber.length() == 14 ) { int count = 0 ; String regularExpression = "[0-9]+" ; // Regular expression to check // for only digits Compile the // ReGex Pattern pattern = Pattern.compile(regularExpression); Matcher matcher = pattern.matcher(accountNumber); if (matcher.matches()) { // only when it matches for ( int i = 0 ; i < accountNumber.length(); i++) { if (accountNumber.charAt(i) == '0' ) { count += 1 ; } } if (count == 14 ) { // all digits are 0 return false ; } else { return true ; } } else { return false ; } } else { return false ; } } } |
JUnit Test Cases
TestBankAccountNumberServices.java
Java
import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; public class TestBankAccountNumberServices { @DisplayName ( "Test check for Invalid bank account" ) @Test public void testCheckForInvalidBankAccountNumber() { BankAccountNumberServices bankAccountNumberServicesObject = new BankAccountNumberServices(); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberMethod1( null )); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberMethod1( "" )); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberMethod1( "00000000000000" )); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberMethod1( "SA123450000000" )); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberMethod1( "1234567" )); // Using Method 2 assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberMethod2( null )); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberMethod2( "" )); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberMethod2( "00000000000000" )); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberMethod2( "SA123450000000" )); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberMethod2( "1234567" )); // Using regular expression check assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberUsingRegularExpression( null )); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberUsingRegularExpression( "" )); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberUsingRegularExpression( "00000000000000" )); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberUsingRegularExpression( "SA123450000000" )); assertEquals( false , bankAccountNumberServicesObject.isValidAccountNumberUsingRegularExpression( "1234567" )); } @DisplayName ( "Test check for Valid bank account" ) @Test public void testCheckForvalidBankAccountNumber() { BankAccountNumberServices bankAccountNumberServicesObject = new BankAccountNumberServices(); assertEquals( true , bankAccountNumberServicesObject.isValidAccountNumberMethod1( "12345678901234" )); assertEquals( true , bankAccountNumberServicesObject.isValidAccountNumberMethod1( "11223344551234" )); assertEquals( true , bankAccountNumberServicesObject.isValidAccountNumberMethod1( "11022033012346" )); // Using method 2 assertEquals( true , bankAccountNumberServicesObject.isValidAccountNumberMethod2( "12345678901234" )); assertEquals( true , bankAccountNumberServicesObject.isValidAccountNumberMethod2( "11223344551234" )); assertEquals( true , bankAccountNumberServicesObject.isValidAccountNumberMethod2( "11022033012346" )); // Using regular expression check assertEquals( true , bankAccountNumberServicesObject.isValidAccountNumberUsingRegularExpression( "12345678901234" )); assertEquals( true , bankAccountNumberServicesObject.isValidAccountNumberUsingRegularExpression( "11223344551234" )); assertEquals( true , bankAccountNumberServicesObject.isValidAccountNumberUsingRegularExpression( "11022033012346" )); } } |
JUnit can be run in the below way
Advantages of writing JUnit:
- We can add perfect validations
- To find out the proper flow and add necessary code which is missing
- To get the expected value matches with the actual value.
Once they are matched, our business logic is getting streamlined easily. We can get the results of positive test cases using the below way