4

I would like to test a method from class1 which calls the singleton class getInstance:

Class ivDomain {

    public String method1() {

        id=Singleton.getInstance().generateId()

        ... code

    }

}

When I do the test using Junit I am getting NullPointerException on the singleton class. How can I fix this?

Adam Wright
  • 48,938
  • 12
  • 131
  • 152
Tejas Shah
  • 531
  • 1
  • 6
  • 6
  • I would suggest you have a bug in your singleton code. Is there any reason you don't use a plain enum for your Singleton? – Peter Lawrey May 01 '11 at 16:55

4 Answers4

4

Classes using statically accessed singletons are a pain to test. Change you ivDomain class to rather take the singleton instance as a parameter to it's constructor and then mock it normally. You should use a Dependency Injection framework (such as Guice) going forward to make this style of development easier.

alpian
  • 4,668
  • 1
  • 18
  • 19
1

You shouldn't have to mock Singleton; just change the code so getInstance() doesn't return a null.

duffymo
  • 305,152
  • 44
  • 369
  • 561
1

The most likely reason - without examining your Singleton's code - is that it's initialization fails to load some external configuration and therefore fails.

Singletons in Automatic Unit Tests can be a problem since sometimes you like them to behave differently for the specific scenario you test (e.g. you want one scenario where generateId returns -1, another when it returns 4354353 and another when it throws a RuntimeException - just so you can see how the code that uses the Singleton works. In such cases a change of design is recommended as Singletons are not amongst the favored design patterns and are somewhat regarded as anti-patterns.

RonK
  • 9,472
  • 8
  • 51
  • 87
  • Actually I am not testing singleton code but the method in ivDomain ivDomain.method1 but the method1 has call to singleton class so, it fails at that point and does not go further. – Tejas Shah May 01 '11 at 23:47
  • here is the singleton code package com.cboe.bo.common.utils; import java.util.TreeMap; import com.cboe.exceptions.ExceptionDetails; import com.cboe.exceptions.NotFoundException; import com.cboe.infrastructureServices.foundationFramework.FoundationFramework; import com.cboe.infrastructureServices.foundationFramework.utilities.Log; import com.cboe.infrastructureServices.instrumentationService.EntityID; import com.cboe.instrumentationService.transactionTimingCommon.TransactionTimer; public class TransactionTimerUtility { – Tejas Shah May 02 '11 at 00:03
  • private static TransactionTimerUtility tteUtility = null; private static TransactionTimer transactionTimer = null; protected boolean infoLogStatus = false; protected boolean sqlLogStatus = false; public static short sourceNumber; private static String isActiveMethod = "Y"; public static int Enter = 0; public static int Leave = 1; public static int LeaveWithException = 2; private static String transactionTimerIndicator; private static final String TTE_REMOTE_VALUE = "local"; private static String[] methodNames; – Tejas Shah May 02 '11 at 00:08
  • private static TreeMap methodIds; private static TreeMap isActiveMethods; private static Long nextID = (long) 0; private static ThreadLocal tLocal = new ThreadLocal() { protected synchronized Long initialValue() { return new Long(nextID++); }}; private static Long get() { return (Long) tLocal.get(); } public TransactionTimerUtility() { infoLogStatus = LogHelper.getInfoLogStatus(); sqlLogStatus = LogHelper.getSqlLogStatus(); } – Tejas Shah May 02 '11 at 00:09
  • static { transactionTimerIndicator = (System.getProperty("transactionTimer") == null) ? TTE_REMOTE_VALUE : System.getProperty("transactionTimer"); if (transactionTimerIndicator.equalsIgnoreCase(TTE_REMOTE_VALUE)) { transactionTimer = FoundationFramework.getInstance() .getInstrumentationService().getTransactionTimerFactory().getLocalTransactionTimer(); } else { transactionTimer = FoundationFramework.getInstance() .getInstrumentationService().getTransactionTimerFactory().getRemoteTransactionTimer(); } – Tejas Shah May 02 '11 at 00:12
  • if (System.getProperty("sourceNumber") != null) { sourceNumber = Short.valueOf(System.getProperty("sourceNumber")); } String methods = System.getProperty("methodNames"); if (methods != null) { methodNames = methods.split(","); System.out.println(" method names are " + methodNames); } methodIds = new TreeMap(); isActiveMethods = new TreeMap(); – Tejas Shah May 02 '11 at 00:13
  • for (String entry : methodNames) { methodIds.put(entry, transactionTimer.registerTransactionIdentifier(entry)); isActiveMethods.put(entry, isActiveMethod); } } public long generateTransId(String reqNbr) { long transId = 0; if (reqNbr != null) { if (reqNbr.equals("0")) transId = get(); else transId = Long.valueOf(reqNbr); transId = EntityID.createID(EntityID.TT_CAS, sourceNumber, Long.valueOf(reqNbr)); Log.information(" TransId from hashCode is : " + transId); } // If transId is 0, we have an issue. return transId; } – Tejas Shah May 02 '11 at 00:13
  • // Get an instance of the TransactionTimerUtility (singleton) public static TransactionTimerUtility getInstance() { return tteUtility; } } – Tejas Shah May 02 '11 at 00:14
  • @Tejas Shah: Can you post this code in the question as an edit? it is not very readable in this manner – RonK May 02 '11 at 08:43
  • Thanks guys I have found my problem. – Tejas Shah May 03 '11 at 15:07
1

check mocking a singleton class

Community
  • 1
  • 1
Lucas de Oliveira
  • 1,642
  • 11
  • 16