pullCommitRun
pullCommitRun

Reputation: 383

Cannot mock classes, throws Exception

Need help in understanding what is wrong with my Unit Tests @Test public void testDownloadSolutionFileAlreadyPresentInLocalRepo() throws Exception { String downloadUrl = "https://artifactory.com/artifactory/com/test-artifact/1.0.0/test-artifact-1.0.0.zip"; String path = "com/test-artifact/1.0.0/"; PowerMockito.mockStatic(ApplicationContext.class); ApplicationContext instance = PowerMockito.mock(ApplicationContext.class); PowerMockito.when(ApplicationContext.getInstance()).thenReturn(instance); PowerMockito.when(instance.getRepositoryDirectory()).thenReturn("\repository");

    SafeFile safeFile = PowerMockito.mock(SafeFile.class);
    PowerMockito.whenNew(SafeFile.class).withArguments(ApplicationContext.getInstance().getReportsDirectory()).thenReturn(safeFile);
    when(safeFile.getChild(Mockito.any())).thenReturn(safeFile);
    SafeFile result = subsystem.downloadSolution(downloadUrl, path);
    Assert.assertEquals(safeFile, result);
}

Inside SC.class

    SafeFile downloadSolution(String downloadUrl, String path) throws Exception {
        try {
            String fileName = downloadUrl.substring(downloadUrl.lastIndexOf(SharedConstants.PATH_DELIMITER) + 1, downloadUrl.length());
            SafeFile rootRepoDir = new SafeFile(ApplicationContext.getInstance().getRepositoryDirectory());
            String pkgSolutionPath = "DownloadedSolutions" + SharedConstants.PATH_DELIMITER + path;
            SafeFile tempFile = rootRepoDir.getChild(pkgSolutionPath + fileName);
            if (tempFile.exists()) {
                return tempFile;
            } else {
some logic ...
return new_file;}

StackTrace:

java.lang.Exception
    at com.system.subsystems.solutioncentral.SC.downloadSolution(SC.java:1017)
    at com.system.subsystems.solutioncentral.SCTest.testDownloadSolutionFileAlreadyPresentInLocalRepo(SCTest.java:832)
    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.internal.runners.TestMethod.invoke(TestMethod.java:68)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:326)
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:310)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:131)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.access$100(PowerMockJUnit47RunnerDelegateImpl.java:59)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner$TestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:147)
    at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.evaluateStatement(PowerMockJUnit47RunnerDelegateImpl.java:107)
    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:298)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:218)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:160)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:134)
    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:136)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:121)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

The unit test exits with a null Pointer Exception. The value of SafeFile rootRepoDir is null, which I don't get why. I have mocked it then why does it show it as null? if I remove this line, PowerMockito.whenNew(SafeFile.class).withAnyArguments().thenReturn(file1); , then the value of rootRepoDir is non-null

I have added SC.class in PrepareForTest, running with PockerMockRunner

Upvotes: 0

Views: 362

Answers (2)

second
second

Reputation: 4259

After you solved your issue I tried to reproduce the issue in another class,
however I only managed to confirm that withAnyArguments does not seem to work.

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Test.class)
public class Test {

    public class Value {
        final String content;

        public Value(String content) {
            this.content = content;
        }   
    }

    public class ValueBuilder {

        private String content;

        public ValueBuilder(String content) {
            this.content = content;
        }

        public Value build() {
            return new Value(content);
        }
    }

    public static class Utils {

        static Utils instance = new Utils();

        static Utils getInstance() {
            return instance;
        }

        public String getToken() {
            return null;
        }
    }

    @Test
    public void test() throws Exception {

        PowerMockito.mockStatic(Utils.class);
        Utils utils = Mockito.mock(Utils.class);
        Mockito.when(utils.getToken()).thenReturn("\\any");
        Mockito.when(Utils.getInstance()).thenReturn(utils);

        ValueBuilder builder = Mockito.mock(ValueBuilder.class);

        // working
        PowerMockito.whenNew(ValueBuilder.class).withArguments(Mockito.any(String.class)).thenReturn(builder);              

        // not working
        //PowerMockito.whenNew(ValueBuilder.class).withAnyArguments().thenReturn(builder);                                  

        // working
        //PowerMockito.whenNew(ValueBuilder.class).withArguments("\\any").thenReturn(builder);                              

        // working
        //PowerMockito.whenNew(ValueBuilder.class).withArguments(Utils.getInstance().getToken()).thenReturn(builder);       

        Mockito.when(builder.build()).thenReturn(new Value("real"));

        new ValueBuilder(Utils.getInstance().getToken()).build();
    }
}

Upvotes: 0

Maciej Kowalski
Maciej Kowalski

Reputation: 26522

You have:

new SafeFile(ApplicationContext.getInstance().getRepositoryDirectory());

you also use mockStatic on the ApplicationContext class:

PowerMockito.mockStatic(ApplicationContext.class);
ApplicationContext mockedApplicationContext = Mockito.mock(ApplicationContext.class);

You do not perform any stubbing on that class though, so when you call ApplicationContext.getInstance() you get the default return value which is NULL. Then you try to call NULL.getRepositoryDirectory() thus NPE.

So make sure you set it up right before you call the SUT:

PowerMockito.when(ApplicationContext.getInstance()).thenReturn(appCtxStub);

Upvotes: 0

Related Questions