Java 如何使用Mockito模拟方法调用链
我有这样一个函数:Java 如何使用Mockito模拟方法调用链,java,junit,mockito,Java,Junit,Mockito,我有这样一个函数: @Override public ClassA createViewModel(ClassB product, ClassC classCVar) throws ModuleException { ClassA classAVar = ClassA.builder().build(); try { if (product !=
@Override
public ClassA createViewModel(ClassB product, ClassC classCVar)
throws ModuleException
{
ClassA classAVar = ClassA.builder().build();
try {
if (product != null && product.getProductData() != null) {
String gl_name = product.getProductData().offers().get(0).productCategory().asProductCategory()
.inlined().map(ProductCategory::glProductGroup).map(ProductCategory.GLProductGroup::symbol)
.orElse("");
classAVar.setName = gl_name;
}
return classAVar;
} catch (Exception e) {
// some lines of code.
}
public String fetchGLNameFunction(ClassB product)
{
String gl_name_result = product.getProductData().offers().get(0).productCategory().asProductCategory()
.inlined().map(ProductCategory::glProductGroup).map(ProductCategory.GLProductGroup::symbol)
.orElse("");
return gl_name_result;
}
@Mock
private ClassA classAVar;
..........
............
@Test
public void testfunction1() throws Exception
{
when(classAVar.fetchGLNameFromAmazonAPI(classBVar)).thenReturn("abc");
我这里有一行,比如字符串gl_name=。。。。。。。。。。。。
它包含一系列方法调用。
现在我想用Mockito模拟这个函数,并希望所有这些函数调用的最终结果,就像gl_name=“abc”
我该怎么做
我创建了一个新函数,并将方法调用链放入其中,如下所示:
@Override
public ClassA createViewModel(ClassB product, ClassC classCVar)
throws ModuleException
{
ClassA classAVar = ClassA.builder().build();
try {
if (product != null && product.getProductData() != null) {
String gl_name = product.getProductData().offers().get(0).productCategory().asProductCategory()
.inlined().map(ProductCategory::glProductGroup).map(ProductCategory.GLProductGroup::symbol)
.orElse("");
classAVar.setName = gl_name;
}
return classAVar;
} catch (Exception e) {
// some lines of code.
}
public String fetchGLNameFunction(ClassB product)
{
String gl_name_result = product.getProductData().offers().get(0).productCategory().asProductCategory()
.inlined().map(ProductCategory::glProductGroup).map(ProductCategory.GLProductGroup::symbol)
.orElse("");
return gl_name_result;
}
@Mock
private ClassA classAVar;
..........
............
@Test
public void testfunction1() throws Exception
{
when(classAVar.fetchGLNameFromAmazonAPI(classBVar)).thenReturn("abc");
现在我尝试创建一个类似这样的模拟:
@Override
public ClassA createViewModel(ClassB product, ClassC classCVar)
throws ModuleException
{
ClassA classAVar = ClassA.builder().build();
try {
if (product != null && product.getProductData() != null) {
String gl_name = product.getProductData().offers().get(0).productCategory().asProductCategory()
.inlined().map(ProductCategory::glProductGroup).map(ProductCategory.GLProductGroup::symbol)
.orElse("");
classAVar.setName = gl_name;
}
return classAVar;
} catch (Exception e) {
// some lines of code.
}
public String fetchGLNameFunction(ClassB product)
{
String gl_name_result = product.getProductData().offers().get(0).productCategory().asProductCategory()
.inlined().map(ProductCategory::glProductGroup).map(ProductCategory.GLProductGroup::symbol)
.orElse("");
return gl_name_result;
}
@Mock
private ClassA classAVar;
..........
............
@Test
public void testfunction1() throws Exception
{
when(classAVar.fetchGLNameFromAmazonAPI(classBVar)).thenReturn("abc");
它仍然给我NullPointerException,因为它正在执行我新创建的函数。在
Mockito
中,您需要定义模拟对象的行为
// create mock
ClassB product = mock(ClassB.class);
// Define the other mocks from your chain:
// X, Y, Z, ...
// define return value for method getProductData()
when(product.getProductData()).thenReturn(X);
when(X.offers()).thenReturn(Y);
when(Y.get(0)()).thenReturn(Z); // And so on.... until the last mock object will return "abc"
您应该模拟要隔离的依赖项,而不是测试的数据/模型。
模拟测试方法的参数将使其可读性大大降低,因为您将不得不模拟许多事情
您的方法链有多个场景,因此通过创建一个对应于每个场景的B实例来测试每个场景。您可以:1)创建一个ClassB对象,该链调用将导致“abc”。2) 或者你模拟一个classB对象,但是你必须模拟每个链接调用。这在某种程度上与得墨忒尔定律有关。3) 或者你在classB中创建了一个方法来执行所有的链式调用,这样你只需要模仿一个方法,我已经编辑了这个问题,并尝试实现了你说的第三个方法。但是它仍然给我带来了NullPointerException。你能发布你的整个测试吗?如何在测试中注入
classAVar
?您需要模拟ClassA.builder().build()
并使其返回模拟对象classAVar
。