Mockito - 存根方法时出现 NullpointerException
Mockito - NullpointerException when stubbing Method
所以我开始为我们的 Java-Spring-项目编写测试。
我用的是JUnit和Mockito。据说,当我使用 when()...thenReturn() 选项时,我可以模拟服务,而无需模拟它们。所以我想做的是设置:
when(classIwantToTest.object.get().methodWhichReturnsAList(input))thenReturn(ListcreatedInsideTheTestClass)
但是无论我执行哪个 when-clause,我总是得到一个 NullpointerException,这当然是有道理的,因为输入是空的。
此外,当我尝试从对象模拟另一个方法时:
when(object.method()).thenReturn(true)
我还得到了一个 Nullpointer,因为该方法需要一个未设置的变量。
但是我想使用 when()..thenReturn() 来绕过创建这个变量等等。我只是想确保,如果任何 class 调用此方法,那么无论如何,只是 return true 或上面的列表。
这基本上是我这边的误解,还是有什么不对的地方?
代码:
public class classIWantToTest implements classIWantToTestFacade{
@Autowired
private SomeService myService;
@Override
public Optional<OutputData> getInformations(final InputData inputData) {
final Optional<OutputData> data = myService.getListWithData(inputData);
if (data.isPresent()) {
final List<ItemData> allData = data.get().getItemDatas();
//do something with the data and allData
return data;
}
return Optional.absent();
}
}
这是我的测试 class:
public class Test {
private InputData inputdata;
private ClassUnderTest classUnderTest;
final List<ItemData> allData = new ArrayList<ItemData>();
@Mock
private DeliveryItemData item1;
@Mock
private DeliveryItemData item2;
@Mock
private SomeService myService;
@Before
public void setUp() throws Exception {
classUnderTest = new ClassUnderTest();
myService = mock(myService.class);
classUnderTest.setService(myService);
item1 = mock(DeliveryItemData.class);
item2 = mock(DeliveryItemData.class);
}
@Test
public void test_sort() {
createData();
when(myService.getListWithData(inputdata).get().getItemDatas());
when(item1.hasSomething()).thenReturn(true);
when(item2.hasSomething()).thenReturn(false);
}
public void createData() {
item1.setSomeValue("val");
item2.setSomeOtherValue("test");
item2.setSomeValue("val");
item2.setSomeOtherValue("value");
allData.add(item1);
allData.add(item2);
}
您尚未存根的方法的默认 return 值对于布尔方法是 false
,对于方法 returning 集合或映射和 null
否则。
这也适用于 when(...)
中的方法调用。在你的例子中 when(myService.getListWithData(inputData).get())
将导致 NullPointerException 因为 myService.getListWithData(inputData)
是 null
- 它之前没有被存根。
一个选项是为所有中间 return 值创建模拟并在使用前存根。例如:
ListWithData listWithData = mock(ListWithData.class);
when(listWithData.get()).thenReturn(item1);
when(myService.getListWithData()).thenReturn(listWithData);
或者,您可以在创建模拟时指定不同的默认答案,使方法 return 成为一个新的模拟而不是 null:RETURNS_DEEP_STUBS
SomeService myService = mock(SomeService.class, Mockito.RETURNS_DEEP_STUBS);
when(myService.getListWithData().get()).thenReturn(item1);
您应该阅读 Mockito.RETURNS_DEEP_STUBS 的 Javadoc,其中更详细地解释了这一点,并且还有一些关于其用法的警告。
希望对您有所帮助。请注意,您的示例代码似乎有更多问题,例如缺少断言或验证语句以及在模拟上调用设置器(没有任何效果)。
我遇到了同样的问题,我的问题很简单,我没有使用@RunWith 正确注释 class。在你的例子中,确保你有:
@RunWith(MockitoJUnitRunner.class)
public class Test {
...
一旦我这样做了,NullPointerExceptions 就消失了。
我遇到了这个问题,我的问题是我使用 any()
而不是 anyInt()
调用我的方法。所以我有:
doAnswer(...).with(myMockObject).thisFuncTakesAnInt(any())
我不得不将其更改为:
doAnswer(...).with(myMockObject).thisFuncTakesAnInt(anyInt())
我不知道为什么会产生 NullPointerException。也许这会帮助下一个可怜的灵魂。
@RunWith(MockitoJUnitRunner.class) //(OR) PowerMockRunner.class
@PrepareForTest({UpdateUtil.class,Log.class,SharedPreferences.class,SharedPreferences.Editor.class})
public class InstallationTest extends TestCase{
@Mock
Context mockContext;
@Mock
SharedPreferences mSharedPreferences;
@Mock
SharedPreferences.Editor mSharedPreferenceEdtor;
@Before
public void setUp() throws Exception
{
// mockContext = Mockito.mock(Context.class);
// mSharedPreferences = Mockito.mock(SharedPreferences.class);
// mSharedPreferenceEdtor = Mockito.mock(SharedPreferences.Editor.class);
when(mockContext.getSharedPreferences(Mockito.anyString(),Mockito.anyInt())).thenReturn(mSharedPreferences);
when(mSharedPreferences.edit()).thenReturn(mSharedPreferenceEdtor);
when(mSharedPreferenceEdtor.remove(Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
when(mSharedPreferenceEdtor.putString(Mockito.anyString(),Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
}
@Test
public void deletePreferencesTest() throws Exception {
}
}
以上所有注释代码都不是必需的
{ mockContext = Mockito.mock(Context.class);
},
如果你使用 @Mock 注释到 Context mockContext;
@Mock
Context mockContext;
但是如果你只使用 @RunWith(MockitoJUnitRunner.class) 它会起作用。根据 Mockito,您可以使用 @Mock 或 Mockito.mock(Context.class); ,
创建模拟对象
因为使用@RunWith(PowerMockRunner.class),我得到了 NullpointerException,而不是我改为@RunWith(MockitoJUnitRunner.class),它工作正常
极端情况:
如果您正在使用 Scala 并尝试在 值 class 上创建一个 any
匹配器,您将得到一个无用的 NPE。
所以给定 case class ValueClass(value: Int) extends AnyVal
,你想要做的是 ValueClass(anyInt)
而不是 any[ValueClass]
when(mock.someMethod(ValueClass(anyInt))).thenAnswer {
...
val v = ValueClass(invocation.getArguments()(0).asInstanceOf[Int])
...
}
另一个 SO question 更具体地说明了这一点,但如果您不知道问题的价值 classes,您就会错过它。
对我来说,我得到 NPE 的原因是我在模拟基元时使用了 Mockito.any()
。我发现通过切换到使用 mockito 的正确变体可以消除错误。
例如,要模拟一个以原语 long
作为参数的函数,而不是使用 any()
,您应该更具体并将其替换为 any(Long.class)
或 Mockito.anyLong()
.
希望对某人有所帮助。
对于未来的读者,使用模拟时 NPE 的另一个原因是忘记像这样初始化模拟:
@Mock
SomeMock someMock;
@InjectMocks
SomeService someService;
@Before
public void setup(){
MockitoAnnotations.initMocks(this); //without this you will get NPE
}
@Test
public void someTest(){
Mockito.when(someMock.someMethod()).thenReturn("some result");
// ...
}
还要确保所有注释都使用 JUnit。
我曾经不小心用 testNG 中的 @Test 创建了一个测试,所以 @Before 无法使用它(在 testNG 中,注释是 @BeforeTest)
Ed Webb 的 帮助了我。相反,您也可以尝试添加
@Rule public Mocks mocks = new Mocks(this);
如果你@RunWith(JUnit4.class)
.
就我而言,我错过了先添加
PowerMockito.spy(ClassWhichNeedToBeStaticMocked.class);
所以这对看到此类错误的人有帮助
java.lang.NullPointerException
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:67)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:42)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:112)
None 这些答案对我有用。这个答案没有解决 OP 的问题,但由于这个 post 是唯一出现在谷歌搜索这个问题上的答案,我在这里分享我的答案。
我在为 Android 编写单元测试时遇到了这个问题。问题是我正在测试的 activity 扩展了 AppCompatActivity
而不是 Activity
。为了解决这个问题,我可以将 AppCompatActivity
替换为 Activity
,因为我并不真的需要它。这可能不是对每个人都可行的解决方案,但希望了解根本原因会对某人有所帮助。
None 以上答案对我有帮助。我一直在努力理解为什么代码在 Java 中有效,但在 Kotlin 中不。
然后我从this thread.
算出来了
你必须创建 class 和成员函数 open
,否则会抛出 NPE。
制作功能后 open
测试开始通过。
你不妨考虑使用编译器的"all-open" plugin:
Kotlin has classes and their members final by default, which makes it inconvenient to use frameworks and libraries such as Spring AOP that require classes to be open. The all-open
compiler plugin adapts Kotlin to the requirements of those frameworks and makes classes annotated with a specific annotation and their members open without the explicit open keyword.
您需要初始化 MockitoAnnotations.initMocks必须调用(此)方法来初始化带注释的字段。
@Before public void initMocks() {
MockitoAnnotations.initMocks(this);
}
有关详细信息,请参阅 Doc
使用 JUnit 5 或更高版本时。您必须注入带有 @Mock
注释的 class
在 @BeforeEach
设置中。
确保初始化模拟。
JUnit4
使用 @Before
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
JUnit5
使用 @BeforeEach
@BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
}
对于 JUnit5
检查,您也使用了正确的导入。
import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
另一个常见问题是方法签名被意外声明为 'final'。
这个问题吸引了很多从事代码库工作的人,这些代码库受制于 Checkstyle,并且已经内化了将成员标记为 final
的需要。
即在 OP 的示例中:
object.method()
确保 method()
未声明为 final
:
public final Object method() {
}
Mockito 无法模拟 final 方法,这将作为包装的 NPE 出现:
Suppressed: org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
隐藏在错误消息中的是以下内容:
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.
因为这是我发现的最接近我遇到的问题的结果,所以这是出现的第一个结果,但我没有找到合适的答案,我会 post 这里的解决方案以供将来遇到任何问题灵魂:
any()
在模拟 class 方法使用原始参数的地方不起作用。
public Boolean getResult(String identifier, boolean switch)
以上将产生与 OP 完全相同的问题。
解决办法,直接包起来:
public Boolean getResult(String identifier, Boolean switch)
后者解决了NPE
在我的例子中,这是由于错误导入了@Test 注解
确保您使用的是以下导入
import org.junit.jupiter.api.Test;
对于 JUnit 5,测试 class 必须注释为:
@ExtendWith(MockitoExtension.class)
进口:
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
我的问题已通过此添加得到解决。
将测试 class 注释为:@ExtendWith(MockitoExtension.class)
。
对我来说,这是因为我在 @BeforeAll
方法中存根了 mock。
MockitoExtension
没有 @BeforeAll
的回调。
public class MockitoExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver
我将 stubbing 移到了它有效的测试方法中!!
在我的例子中,这是因为注释使用错误。我正在使用 junit 4 进行测试,并在初始化时使用 @BeforeEach
而不是 @Before
。
将其更改为 @Before
,效果非常好。
就我而言,这是 when()
的错误导入。
我不小心用了import static reactor.core.publisher.Mono.when
。
在我的例子中,我在映射器声明中缺少注释 @mock
。
在我的例子中,Intellij 使用 org.junit.jupiter.api.Test
(Junit5) 而不是 import org.junit.Test
of (Junit4) 创建了 Test,这显然导致所有 bean 都为空。
另外,确保 class 和测试方法是 public
这就是 google 带我去的地方,当时我有与 Junit 5 相同的 NullPointerException
,但在我的 maven 项目中正确使用了 @ExtendWith(MockitoExtension.class)
。
结果我没有在我的 pom.xml 中包含 maven-surefire-plugin
,这意味着 @ExtendWith
实际上没有做任何事情!
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
...
在我的例子中,一个测试方法调用另一个方法作为参数:
Mockito.`when`(repository.getItems(prefs.getUser().id)).thenReturn(listOf())`
虽然 repository
被模拟,但 prefs.getUser().id)
将抛出 NPE。所以,首先我们应该模拟一个参数,例如,
Mockito.`when`(prefs.getUser()).thenReturn(User(id = 1, name = "user"))`
我们也应该模拟prefs
。没查到,换了个库,sorry
我试图模拟一个“最终”方法,这显然是问题所在。
处理此问题的正确方法是使用接口并模拟该接口,但我无法控制“最终”方法所在的库。
Mockito 2 可以处理模拟 final 方法。将文本文件添加到项目的 src/test/resources/mockito-extensions 目录,名为 org.mockito.plugins.MockMaker 并添加一行文本:
mock-maker-inline
在那之后,模拟 final 方法应该可以正常工作。
检查您使用的是哪个版本的 Junit。在 Maven/Gradle 构建工具中,如果您设置使用 testRuntimeOnly 'junit5'
,那么它可能不需要 @RunWith
,因为它不可用,它在 Junit5 中被替换为 @ExtendWith
。
所以我开始为我们的 Java-Spring-项目编写测试。
我用的是JUnit和Mockito。据说,当我使用 when()...thenReturn() 选项时,我可以模拟服务,而无需模拟它们。所以我想做的是设置:
when(classIwantToTest.object.get().methodWhichReturnsAList(input))thenReturn(ListcreatedInsideTheTestClass)
但是无论我执行哪个 when-clause,我总是得到一个 NullpointerException,这当然是有道理的,因为输入是空的。
此外,当我尝试从对象模拟另一个方法时:
when(object.method()).thenReturn(true)
我还得到了一个 Nullpointer,因为该方法需要一个未设置的变量。
但是我想使用 when()..thenReturn() 来绕过创建这个变量等等。我只是想确保,如果任何 class 调用此方法,那么无论如何,只是 return true 或上面的列表。
这基本上是我这边的误解,还是有什么不对的地方?
代码:
public class classIWantToTest implements classIWantToTestFacade{
@Autowired
private SomeService myService;
@Override
public Optional<OutputData> getInformations(final InputData inputData) {
final Optional<OutputData> data = myService.getListWithData(inputData);
if (data.isPresent()) {
final List<ItemData> allData = data.get().getItemDatas();
//do something with the data and allData
return data;
}
return Optional.absent();
}
}
这是我的测试 class:
public class Test {
private InputData inputdata;
private ClassUnderTest classUnderTest;
final List<ItemData> allData = new ArrayList<ItemData>();
@Mock
private DeliveryItemData item1;
@Mock
private DeliveryItemData item2;
@Mock
private SomeService myService;
@Before
public void setUp() throws Exception {
classUnderTest = new ClassUnderTest();
myService = mock(myService.class);
classUnderTest.setService(myService);
item1 = mock(DeliveryItemData.class);
item2 = mock(DeliveryItemData.class);
}
@Test
public void test_sort() {
createData();
when(myService.getListWithData(inputdata).get().getItemDatas());
when(item1.hasSomething()).thenReturn(true);
when(item2.hasSomething()).thenReturn(false);
}
public void createData() {
item1.setSomeValue("val");
item2.setSomeOtherValue("test");
item2.setSomeValue("val");
item2.setSomeOtherValue("value");
allData.add(item1);
allData.add(item2);
}
您尚未存根的方法的默认 return 值对于布尔方法是 false
,对于方法 returning 集合或映射和 null
否则。
这也适用于 when(...)
中的方法调用。在你的例子中 when(myService.getListWithData(inputData).get())
将导致 NullPointerException 因为 myService.getListWithData(inputData)
是 null
- 它之前没有被存根。
一个选项是为所有中间 return 值创建模拟并在使用前存根。例如:
ListWithData listWithData = mock(ListWithData.class);
when(listWithData.get()).thenReturn(item1);
when(myService.getListWithData()).thenReturn(listWithData);
或者,您可以在创建模拟时指定不同的默认答案,使方法 return 成为一个新的模拟而不是 null:RETURNS_DEEP_STUBS
SomeService myService = mock(SomeService.class, Mockito.RETURNS_DEEP_STUBS);
when(myService.getListWithData().get()).thenReturn(item1);
您应该阅读 Mockito.RETURNS_DEEP_STUBS 的 Javadoc,其中更详细地解释了这一点,并且还有一些关于其用法的警告。
希望对您有所帮助。请注意,您的示例代码似乎有更多问题,例如缺少断言或验证语句以及在模拟上调用设置器(没有任何效果)。
我遇到了同样的问题,我的问题很简单,我没有使用@RunWith 正确注释 class。在你的例子中,确保你有:
@RunWith(MockitoJUnitRunner.class)
public class Test {
...
一旦我这样做了,NullPointerExceptions 就消失了。
我遇到了这个问题,我的问题是我使用 any()
而不是 anyInt()
调用我的方法。所以我有:
doAnswer(...).with(myMockObject).thisFuncTakesAnInt(any())
我不得不将其更改为:
doAnswer(...).with(myMockObject).thisFuncTakesAnInt(anyInt())
我不知道为什么会产生 NullPointerException。也许这会帮助下一个可怜的灵魂。
@RunWith(MockitoJUnitRunner.class) //(OR) PowerMockRunner.class
@PrepareForTest({UpdateUtil.class,Log.class,SharedPreferences.class,SharedPreferences.Editor.class})
public class InstallationTest extends TestCase{
@Mock
Context mockContext;
@Mock
SharedPreferences mSharedPreferences;
@Mock
SharedPreferences.Editor mSharedPreferenceEdtor;
@Before
public void setUp() throws Exception
{
// mockContext = Mockito.mock(Context.class);
// mSharedPreferences = Mockito.mock(SharedPreferences.class);
// mSharedPreferenceEdtor = Mockito.mock(SharedPreferences.Editor.class);
when(mockContext.getSharedPreferences(Mockito.anyString(),Mockito.anyInt())).thenReturn(mSharedPreferences);
when(mSharedPreferences.edit()).thenReturn(mSharedPreferenceEdtor);
when(mSharedPreferenceEdtor.remove(Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
when(mSharedPreferenceEdtor.putString(Mockito.anyString(),Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
}
@Test
public void deletePreferencesTest() throws Exception {
}
}
以上所有注释代码都不是必需的
{ mockContext = Mockito.mock(Context.class);
},
如果你使用 @Mock 注释到 Context mockContext;
@Mock
Context mockContext;
但是如果你只使用 @RunWith(MockitoJUnitRunner.class) 它会起作用。根据 Mockito,您可以使用 @Mock 或 Mockito.mock(Context.class); ,
创建模拟对象因为使用@RunWith(PowerMockRunner.class),我得到了 NullpointerException,而不是我改为@RunWith(MockitoJUnitRunner.class),它工作正常
极端情况:
如果您正在使用 Scala 并尝试在 值 class 上创建一个 any
匹配器,您将得到一个无用的 NPE。
所以给定 case class ValueClass(value: Int) extends AnyVal
,你想要做的是 ValueClass(anyInt)
而不是 any[ValueClass]
when(mock.someMethod(ValueClass(anyInt))).thenAnswer {
...
val v = ValueClass(invocation.getArguments()(0).asInstanceOf[Int])
...
}
另一个 SO question 更具体地说明了这一点,但如果您不知道问题的价值 classes,您就会错过它。
对我来说,我得到 NPE 的原因是我在模拟基元时使用了 Mockito.any()
。我发现通过切换到使用 mockito 的正确变体可以消除错误。
例如,要模拟一个以原语 long
作为参数的函数,而不是使用 any()
,您应该更具体并将其替换为 any(Long.class)
或 Mockito.anyLong()
.
希望对某人有所帮助。
对于未来的读者,使用模拟时 NPE 的另一个原因是忘记像这样初始化模拟:
@Mock
SomeMock someMock;
@InjectMocks
SomeService someService;
@Before
public void setup(){
MockitoAnnotations.initMocks(this); //without this you will get NPE
}
@Test
public void someTest(){
Mockito.when(someMock.someMethod()).thenReturn("some result");
// ...
}
还要确保所有注释都使用 JUnit。 我曾经不小心用 testNG 中的 @Test 创建了一个测试,所以 @Before 无法使用它(在 testNG 中,注释是 @BeforeTest)
Ed Webb 的
@Rule public Mocks mocks = new Mocks(this);
如果你@RunWith(JUnit4.class)
.
就我而言,我错过了先添加
PowerMockito.spy(ClassWhichNeedToBeStaticMocked.class);
所以这对看到此类错误的人有帮助
java.lang.NullPointerException
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:67)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:42)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:112)
None 这些答案对我有用。这个答案没有解决 OP 的问题,但由于这个 post 是唯一出现在谷歌搜索这个问题上的答案,我在这里分享我的答案。
我在为 Android 编写单元测试时遇到了这个问题。问题是我正在测试的 activity 扩展了 AppCompatActivity
而不是 Activity
。为了解决这个问题,我可以将 AppCompatActivity
替换为 Activity
,因为我并不真的需要它。这可能不是对每个人都可行的解决方案,但希望了解根本原因会对某人有所帮助。
None 以上答案对我有帮助。我一直在努力理解为什么代码在 Java 中有效,但在 Kotlin 中不。
然后我从this thread.
算出来了你必须创建 class 和成员函数 open
,否则会抛出 NPE。
制作功能后 open
测试开始通过。
你不妨考虑使用编译器的"all-open" plugin:
Kotlin has classes and their members final by default, which makes it inconvenient to use frameworks and libraries such as Spring AOP that require classes to be open. The
all-open
compiler plugin adapts Kotlin to the requirements of those frameworks and makes classes annotated with a specific annotation and their members open without the explicit open keyword.
您需要初始化 MockitoAnnotations.initMocks必须调用(此)方法来初始化带注释的字段。
@Before public void initMocks() {
MockitoAnnotations.initMocks(this);
}
有关详细信息,请参阅 Doc
使用 JUnit 5 或更高版本时。您必须注入带有 @Mock
注释的 class
在 @BeforeEach
设置中。
确保初始化模拟。
JUnit4
使用 @Before
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
JUnit5
使用 @BeforeEach
@BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
}
对于 JUnit5
检查,您也使用了正确的导入。
import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
另一个常见问题是方法签名被意外声明为 'final'。
这个问题吸引了很多从事代码库工作的人,这些代码库受制于 Checkstyle,并且已经内化了将成员标记为 final
的需要。
即在 OP 的示例中:
object.method()
确保 method()
未声明为 final
:
public final Object method() {
}
Mockito 无法模拟 final 方法,这将作为包装的 NPE 出现:
Suppressed: org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
隐藏在错误消息中的是以下内容:
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.
因为这是我发现的最接近我遇到的问题的结果,所以这是出现的第一个结果,但我没有找到合适的答案,我会 post 这里的解决方案以供将来遇到任何问题灵魂:
any()
在模拟 class 方法使用原始参数的地方不起作用。
public Boolean getResult(String identifier, boolean switch)
以上将产生与 OP 完全相同的问题。
解决办法,直接包起来:
public Boolean getResult(String identifier, Boolean switch)
后者解决了NPE
在我的例子中,这是由于错误导入了@Test 注解
确保您使用的是以下导入
import org.junit.jupiter.api.Test;
对于 JUnit 5,测试 class 必须注释为:
@ExtendWith(MockitoExtension.class)
进口:
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
我的问题已通过此添加得到解决。
将测试 class 注释为:@ExtendWith(MockitoExtension.class)
。
对我来说,这是因为我在 @BeforeAll
方法中存根了 mock。
MockitoExtension
没有 @BeforeAll
的回调。
public class MockitoExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver
我将 stubbing 移到了它有效的测试方法中!!
在我的例子中,这是因为注释使用错误。我正在使用 junit 4 进行测试,并在初始化时使用 @BeforeEach
而不是 @Before
。
将其更改为 @Before
,效果非常好。
就我而言,这是 when()
的错误导入。
我不小心用了import static reactor.core.publisher.Mono.when
。
在我的例子中,我在映射器声明中缺少注释 @mock
。
在我的例子中,Intellij 使用 org.junit.jupiter.api.Test
(Junit5) 而不是 import org.junit.Test
of (Junit4) 创建了 Test,这显然导致所有 bean 都为空。
另外,确保 class 和测试方法是 public
这就是 google 带我去的地方,当时我有与 Junit 5 相同的 NullPointerException
,但在我的 maven 项目中正确使用了 @ExtendWith(MockitoExtension.class)
。
结果我没有在我的 pom.xml 中包含 maven-surefire-plugin
,这意味着 @ExtendWith
实际上没有做任何事情!
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
...
在我的例子中,一个测试方法调用另一个方法作为参数:
Mockito.`when`(repository.getItems(prefs.getUser().id)).thenReturn(listOf())`
虽然 repository
被模拟,但 prefs.getUser().id)
将抛出 NPE。所以,首先我们应该模拟一个参数,例如,
Mockito.`when`(prefs.getUser()).thenReturn(User(id = 1, name = "user"))`
我们也应该模拟prefs
。没查到,换了个库,sorry
我试图模拟一个“最终”方法,这显然是问题所在。
处理此问题的正确方法是使用接口并模拟该接口,但我无法控制“最终”方法所在的库。
Mockito 2 可以处理模拟 final 方法。将文本文件添加到项目的 src/test/resources/mockito-extensions 目录,名为 org.mockito.plugins.MockMaker 并添加一行文本:
mock-maker-inline
在那之后,模拟 final 方法应该可以正常工作。
检查您使用的是哪个版本的 Junit。在 Maven/Gradle 构建工具中,如果您设置使用 testRuntimeOnly 'junit5'
,那么它可能不需要 @RunWith
,因为它不可用,它在 Junit5 中被替换为 @ExtendWith
。