简体   繁体   中英

Junit test fail for the java.lang.NullPointerException

I work to test a class with the Junit and I get an NullPointerException .

The class I would like to test is provided below,

@Component
public class EmailageConnector {

    private static final Logger LOG = LoggerFactory.getLogger( EmailageConnector.class );

    private static final String BASIC_AUTHORIZATION = "Basic ";

    @Autowired
    private EmailageConfigHolder emailageConfigHolder;

    @Autowired
    private EntityServiceConnectable<EmailageResponseDto> connector;

    private String authorization;

    @PostConstruct
    void createAuthorization() {
        final String credentials = String.format( "%s%s%s", emailageConfigHolder.getAccountId(), ":", emailageConfigHolder.getApiKey() );
        authorization = BASIC_AUTHORIZATION + encodeBase64String( credentials.getBytes() );
    }

    // ========================================================================

    public ServiceResponse<EmailageResponseDto> call( final RequestInformation requestInfo, final EmailageRequestDto request ) {

        if( LOG.isDebugEnabled() ) {
            LOG.debug( "call emailage [ requestInfo: {} - request: {}]",
                       String.format( "%s", requestInfo ),
                       String.format( "%s", request ) );
        }

        return connector.call( request, createHeaders() );
    }

    // ========================================================================

    private HttpHeaders createHeaders() {
        final HttpHeaders headers = new HttpHeaders();

        headers.add( AUTHORIZATION, authorization );
        return headers;
    }

}

This is my test class,

@RunWith( MockitoJUnitRunner.class )
public class EmailageConnectorTest {

    @InjectMocks
    private EmailageConnector connector;

    @Spy
    private EmailageConfigHolder configHolder;

    @Mock
    EntityServiceConnectable<EmailageResponseDto> serviceConnector;

    @Captor
    private ArgumentCaptor<UriParam<?>> captor;

    @Captor
    private ArgumentCaptor<HttpHeaders> headerCaptor;

    @Before
    public void setUp() {
        configHolder.setApiKey( "api-key-123456" );
        configHolder.setAccountId( "ratepay-group" );
        connector.createAuthorization();
    }

    @Test
    public void call() {

        RequestInformation requestInfo = new TestRequestInformation();

        when( serviceConnector.call( Mockito.any( HttpHeaders.class ), Mockito.any() ) )
                .thenReturn( ServiceResponseFactory.withError( "error", 500 ) );

        ServiceResponse<EmailageResponseDto> response = connector.call( requestInfo, createTestEmailageRequestDto() );

        assertEquals( Integer.valueOf( 500 ), response.getHttpStatus() );
        assertEquals( "error", response.getErrorMessage() );

        verify( serviceConnector ).call( headerCaptor.capture(), captor.capture() );

        assertEquals( 3, captor.getAllValues().size() );
        assertEquals( "api_id", captor.getAllValues().get( 0 ).getName() );
        assertEquals( "api-id-12345", captor.getAllValues().get( 0 ).getValue() );
        assertEquals( "token", captor.getAllValues().get( 1 ).getName() );
        assertEquals( "token-1234", captor.getAllValues().get( 1 ).getValue() );
        assertEquals( "include", captor.getAllValues().get( 2 ).getName() );
        assertEquals( "scores", String.valueOf( ( (SimpleQueryUriParam) captor.getAllValues().get( 2 ) ).getValue()[0] ) );
        assertEquals( GW_ID, headerCaptor.getValue().getFirst( HEADER_GATEWAY_REQUEST_ID ) );
        assertEquals( TRX_ID, headerCaptor.getValue().getFirst( HEADER_TRANSACTION_ID ) );
        assertEquals( "Basic cmF0ZXBheS1ncm91cDphcGkta2V5LTEyMzQ1Ng==", headerCaptor.getValue().getFirst( AUTHORIZATION ) );
    }

    private EmailageRequestDto createTestEmailageRequestDto() {

        EmailageRequestDto dto = new EmailageRequestBuilder().build();
        return dto;
    }
}

The interface for the EntityServiceConnectable is provided below,

public interface EntityServiceConnectable<RESPONSE> extends ServiceConnectable<RESPONSE> {

    ServiceResponse<RESPONSE> call(Object var1, RequestInformation var2, UriParam... var3);

    ServiceResponse<RESPONSE> call(Object var1, HttpHeaders var2, UriParam... var3);

    ServiceResponse<RESPONSE> call(Object var1, UriParam... var2);
}

The test is failing here,

ServiceResponse<EmailageResponseDto> response = connector.call( requestInfo, createTestEmailageRequestDto() );

Here is the error stack for the test,

java.lang.NullPointerException
    at com.ratepay.ella.service.io.EmailageConnectorTest.call(EmailageConnectorTest.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79)
    at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85)
    at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
    at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

[MockitoHint] EmailageConnectorTest.call (see javadoc for MockitoHint):
[MockitoHint] 1. Unused... -> at com.ratepay.ella.service.io.EmailageConnectorTest.call(EmailageConnectorTest.java:79)
[MockitoHint]  ...args ok? -> at com.ratepay.ella.service.io.EmailageConnector.call(EmailageConnector.java:65)

I debugged the setup and provided the screenshot below,

在此输入图像描述

What do I miss here?

Edit:
For JUnit5 and mockito refer to this answer:
How to use Mockito with JUnit5
I've updated the example below as well.

Edit2: As the TO did not state which JUnit version or mockito version is being used, I will try to edit the answer if still does not work.


Thanks to @helospark for poining this out.

Using the Runner or the Rule does not work with JUnit5, so probably Mockito Version 2 should be used.

With Mockito Version 1 , an explictly call to the init Method is required.


    @BeforeEach
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }


For Junit5 and the latest Mockito version (2.27) the test class should look like this:

class InnerClass {
    public void doSomething(String fileName) {
    }
}

class SomeClass {

    InnerClass innerClass;

    public boolean doSomething(String fileName) {
        innerClass.doSomething(fileName);
        return true;
    }
}

@ExtendWith(MockitoExtension.class)
class SomeClassTest {

    @InjectMocks
    SomeClass someClass;

    @Mock
    InnerClass innerClass;

    @Test
    public void test() {
        someClass.doSomething("test");
        Mockito.verify(innerClass, Mockito.times(1)).doSomething(Mockito.any());
    }
}

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