简体   繁体   中英

How to initialize a private variable in a final class using REFLECTION or any other API?

This may sound awkward but I am trying to initialize a private variable in a final class. I've done this many times and I know it works very well using Reflection but I have never really done this with a final class. Since I cannot instantiate the class i cannot pass any object to set the variable and this is where I am stuck.

Final class

public final class LoggingHandler implements ILoggingHandler {

private Log generalLog; 

/**
 * @param log The general log.
 */
private void setGeneralLog(Log log) {
    generalLog = log;
}

/**
 * @return The general log.
 */
private Log getGeneralLog() {
    return generalLog;
}

JUnit

@Test
public void testSendDocuments() throws Exception {
    AppContext.setApplicationContext( applicationContext );
    IClientUserDto iClientUserDto = mock( IClientUserDto.class );

    DocusignRESTProvider docusignRestProvider = new DocusignRESTProvider();
    docusignRestProvider.setLoggingHandler( iloggingHandler );
    docusignRestProvider.setDocumentManager( iDocumentManager );
    docusignRestProvider.setConfiguration( iProviderConfiguration );
    docusignRestProvider.setManager( iManager );

    Field field = LoggingHandler.class.getDeclaredField( "generalLog" );
    field.setAccessible( true );
    field.set( new Object(), log );

    when( iTransformer.transformRequest( any( SendDocumentsTransformerArgs.class ) ) ).thenReturn( iTransformerResult );
    docusignRestProvider.sendDocuments( iClientUserDto, iDocumentSet );
}

log is a mocked object.

stack trace:

java.lang.IllegalArgumentException: Can not set org.apache.commons.logging.Log field com.mercuryinsurance.esignature.common.logging.LoggingHandler.generalLog to java.lang.Object
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:75)
at java.lang.reflect.Field.set(Field.java:741)
at test.com.mercuryinsurance.esignature.integration.provider.docusign.rest.TestDocusignRESTProvider.testSendDocuments(TestDocusignRESTProvider.java:167)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Can someone let me know what other approach is there to test such a condition and how?

Thanks

You are misusing the concept of a final class. Final classes CAN be instantiated, they cannot be inherited. So, in your case LoggingHandler can and should be instantiated unless its constructor is private. But if its constructor is private - what is the point of such a class implementing an interface?

You should create public setters and getters for Log field, instantiate a LoggingHandler instance and pass there a mock of you Log object within test. You can do whatever verifications you need on that mock later.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM