use*_*542 49 java testing junit mockito stubbing
所以我开始为Java-Spring项目编写测试.
我使用的是JUnit和Mockito.据说,当我使用when()... thenReturn()选项时,我可以模拟服务,而不需要模拟它们.所以我想做的是,设置:
when(classIwantToTest.object.get().methodWhichReturnsAList(input))thenReturn(ListcreatedInsideTheTestClass)
Run Code Online (Sandbox Code Playgroud)
但无论我在哪个when子句中,我总是得到一个NullpointerException,当然这是有意义的,因为输入是null.
当我尝试从对象模拟另一个方法时:
when(object.method()).thenReturn(true)
Run Code Online (Sandbox Code Playgroud)
在那里我也得到一个Nullpointer,因为该方法需要一个未设置的变量.
但我想使用when().. thenReturn()来绕过创建这个变量等等.我只是想确保,如果任何类调用此方法,那么无论如何,只返回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();
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的测试类:
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);
}
Run Code Online (Sandbox Code Playgroud)
Rya*_*ton 98
我有这个问题,我的问题是我用any()而不是调用我的方法anyInt().所以我有:
doAnswer(...).with(myMockObject).thisFuncTakesAnInt(any())
Run Code Online (Sandbox Code Playgroud)
我不得不把它改成:
doAnswer(...).with(myMockObject).thisFuncTakesAnInt(anyInt())
Run Code Online (Sandbox Code Playgroud)
我不知道为什么会产生NullPointerException.也许这将有助于下一个可怜的灵魂.
ahu*_*ahu 49
您尚未存根的方法的默认返回值是false布尔方法,空集合或返回集合或映射的方法的映射null.
这也适用于内部的方法调用when(...).在你的例子中when(myService.getListWithData(inputData).get())会导致NullPointerException,因为myService.getListWithData(inputData)它null- 之前没有被存根.
一个选项是为所有中间返回值创建模拟,并在使用前将它们存根.例如:
ListWithData listWithData = mock(ListWithData.class);
when(listWithData.get()).thenReturn(item1);
when(myService.getListWithData()).thenReturn(listWithData);
Run Code Online (Sandbox Code Playgroud)
或者,您可以在创建模拟时指定不同的默认答案,以使方法返回新的模拟而不是null: RETURNS_DEEP_STUBS
SomeService myService = mock(SomeService.class, Mockito.RETURNS_DEEP_STUBS);
when(myService.getListWithData().get()).thenReturn(item1);
Run Code Online (Sandbox Code Playgroud)
您应该阅读Mockito.RETURNS_DEEP_STUBS的Javadoc,它更详细地解释了这一点,并且还有一些关于其用法的警告.
我希望这有帮助.请注意,您的示例代码似乎有更多问题,例如缺少断言或验证语句以及在模拟上调用setter(这没有任何影响).
小智 43
我有同样的问题,我的问题只是我没有使用@RunWith正确地注释该类.在您的示例中,请确保您具有:
@RunWith(MockitoJUnitRunner.class)
public class Test {
...
Run Code Online (Sandbox Code Playgroud)
一旦我这样做,NullPointerExceptions就消失了.
Tan*_*nel 20
由于这是我发现的最接近我遇到的问题的结果,这是出现的第一个结果,而且我没有找到合适的答案,我将在这里为未来的可怜的灵魂发布解决方案:
any()在模拟类方法使用原始参数的情况下不起作用。
public Boolean getResult(String identifier, boolean switch)
Run Code Online (Sandbox Code Playgroud)
以上将产生与 OP 相同的问题。
解决方案,只需将其包裹起来:
public Boolean getResult(String identifier, Boolean switch)
Run Code Online (Sandbox Code Playgroud)
后者解决了NPE。
gar*_*may 11
确保你初始化你的模拟。
JUnit4 用 @Before
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
Run Code Online (Sandbox Code Playgroud)
JUnit5 用 @BeforeEach
@BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
}
Run Code Online (Sandbox Code Playgroud)
为了JUnit5检查,您还使用了正确的导入。
import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
Run Code Online (Sandbox Code Playgroud)
对于将来的读者,使用模拟时导致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");
// ...
}
Run Code Online (Sandbox Code Playgroud)
还要确保所有注释都使用JUnit。我曾经不小心用testNG的@Test创建了一个测试,所以@Before不能使用它(在testNG中,注释是@BeforeTest)
对我来说,获得NPE的原因是我Mockito.any()在模拟基元时使用了NPE 。我发现通过切换到使用来自Mockito的正确变体可以消除错误。
例如,要模拟以原始类型long为参数的函数,而不是使用any(),应更加具体,并用any(Long.class)或替换Mockito.anyLong()。
希望能对某人有所帮助。
特殊情况:
如果您使用Scala并尝试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])
...
}
Run Code Online (Sandbox Code Playgroud)
另一个SO 问题更具体地说明了这一点,但是当您不知道问题与值类有关时,您就会错过它。
对于 JUnit 5,测试类必须注释为:
@ExtendWith(MockitoExtension.class)
Run Code Online (Sandbox Code Playgroud)
进口:
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
Run Code Online (Sandbox Code Playgroud)
我的问题通过此添加得到解决。
您需要初始化 MockitoAnnotations.initMocks(this) 方法来初始化带注释的字段。
@Before public void initMocks() {
MockitoAnnotations.initMocks(this);
}
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅文档
检查方法签名是否未声明为 final
这个问题引起了很多从事代码库工作的人的注意,这些代码库受 Checkstyle 的约束,并且已经内化了将成员标记为final.
即在OP的例子中:
object.method()
确保method()未声明为final:
public final Object method() {
}
Run Code Online (Sandbox Code Playgroud)
Mockito 无法模拟最终方法,这将作为包装的 NPE 出现:
Suppressed: org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Run Code Online (Sandbox Code Playgroud)
错误消息中隐藏着以下内容:
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.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
101563 次 |
| 最近记录: |