Junit 测试静态方法内部无效方法已调用一次

Junit 测试静态方法内部无效方法已调用一次,junit,mockito,junit4,powermock,powermockito,Junit,Mockito,Junit4,Powermock,Powermockito,我需要一些测试方面的帮助。具有以下方法: @PrePersist public void prePersist(Tag tag) { if (tagService.listUserTags(tag.getUser()) .size() > Constants.Tags.maxPerUser) { TaskUtils.createTask(url, param); } } 我想

我需要一些测试方面的帮助。具有以下方法:

    @PrePersist
    public void prePersist(Tag tag) {

        if (tagService.listUserTags(tag.getUser())
                .size() > Constants.Tags.maxPerUser) {
            TaskUtils.createTask(url, param);
        }
    }
我想测试TaskUtils.createTask()是否被调用一次,但我不想执行其中的代码。我试过这样做:

        @Test
        @PrepareForTest(TaskUtils.class)
        public void testPrePersistMethodWhenTagCountOverLimit() {
            [...]
            when(tags.size()).thenReturn(Constants.Tags.maxPerUser + 1);
            when (tagService.listUserTags(tag.getUser())).thenReturn(tags);

            PowerMockito.mockStatic(TaskUtils.class);
            PowerMockito.doNothing().when(TaskUtils.class, "createTask", Mockito.any(String.class), Mockito.any(String.class));                                            

            Method method = ClassUtils.getMethodWithAnnotation(TagListener.class, PrePersist.class);
            method.invoke(tagListener, tag); //here the prePersist method is called

            PowerMockito.verifyStatic( Mockito.times(1));

        }
但是方法TaskUtils.createTask()实际上是执行的,尽管没有执行任何操作。 堆栈跟踪的一部分:

java.lang.NullPointerException
    at fi.util.TaskUtils.createTask(TaskUtils.java:90)
    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.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1873)
    at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:773)
    at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:753)
    at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:466)
    at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:106)
    at fi.intra.test.domain.listener.TestTagListener.testPrePersistMethodWhenTagCountOverLimit(TestTagListener.java:92)

有什么想法吗?

以下是有效的,应该与您的案例相同:

我使用Gradle进行构建,并添加了以下依赖项:

testCompile组:'org.powermock',名称:'powermock mockito release full',版本:'1.6.4'

测试

package sojava.mocking;

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

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.times;
import static org.powermock.api.mockito.PowerMockito.*;

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyData.class)
public class PowerMockitoTests {

    @Test
    public void static_method_when_mocked_does_nothing() throws Exception {
        int amount = 123;

        // Arrange
        mockStatic(MyData.class);
        doNothing().when(MyData.class, "increment", amount);

        // Action
        new MyDataWrapper().increment(amount);
        verifyStatic(times(1));
        MyData.increment(amount);

        // Assert
        assertThat(MyData.getCount()).isEqualTo(0);
    }
}
你看到这个代码了吗

new MyDataWrapper().increment(amount);
verifyStatic(times(1));
MyData.increment(amount);
这很尴尬,但这就是它的工作原理。要测试静态方法是否被多次调用?然后调用该方法,然后调用
verifyStatic()
,然后再次调用该静态方法。最后一个调用将触发检查

使用静态方法初始化

package sojava.mocking;

public class MyDataWrapper {
    public void increment(int amount) {
        MyData.increment(amount);
    }
}
包含静态方法的类

package sojava.mocking;

public class MyDataWrapper {
    public void increment(int amount) {
        MyData.increment(amount);
    }
}
包sojava.mocking

public class MyData {

    private static int count = 0;

    private MyData() {
    }

    public static void increment(int amount) {
        count += amount;
    }

    public static int getCount() {
        return count;
    }
}

更多样本:更多样本位于其上。

以下内容适用于您的案例:

我使用Gradle进行构建,并添加了以下依赖项:

testCompile组:'org.powermock',名称:'powermock mockito release full',版本:'1.6.4'

测试

package sojava.mocking;

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

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.times;
import static org.powermock.api.mockito.PowerMockito.*;

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyData.class)
public class PowerMockitoTests {

    @Test
    public void static_method_when_mocked_does_nothing() throws Exception {
        int amount = 123;

        // Arrange
        mockStatic(MyData.class);
        doNothing().when(MyData.class, "increment", amount);

        // Action
        new MyDataWrapper().increment(amount);
        verifyStatic(times(1));
        MyData.increment(amount);

        // Assert
        assertThat(MyData.getCount()).isEqualTo(0);
    }
}
你看到这个代码了吗

new MyDataWrapper().increment(amount);
verifyStatic(times(1));
MyData.increment(amount);
这很尴尬,但这就是它的工作原理。要测试静态方法是否被多次调用?然后调用该方法,然后调用
verifyStatic()
,然后再次调用该静态方法。最后一个调用将触发检查

使用静态方法初始化

package sojava.mocking;

public class MyDataWrapper {
    public void increment(int amount) {
        MyData.increment(amount);
    }
}
包含静态方法的类

package sojava.mocking;

public class MyDataWrapper {
    public void increment(int amount) {
        MyData.increment(amount);
    }
}
包sojava.mocking

public class MyData {

    private static int count = 0;

    private MyData() {
    }

    public static void increment(int amount) {
        count += amount;
    }

    public static int getCount() {
        return count;
    }
}

更多示例:更多示例位于其上。

是参数url和参数字符串的类型?@pvpkiran,是的,我假设您有此
@RunWith(PowerMockRunner.class)
。其余的代码看起来很好是的,我有@RunWith(PowerMockRunner.class),如果你知道测试类中作为url和param传递的确切参数,那么试着直接使用它,而不是Mockito.any(String.class)。参数url和param String的类型是吗?@pvpkiran,是的,我假设你有这个
@RunWith(PowerMockRunner.class)
。其余代码看起来不错是的,我有@RunWith(PowerMockRunner.class),如果您知道测试类中作为url和param传递的确切参数,那么请尝试直接使用该参数,而不是Mockito.any(String.class)。