使用 Mockitos 进行单元测试未按预期工作
Unit testing with Mockitos not working as expected
我是 Mockito 的新手,我想为一些遗留代码编写单元测试。在测试我的特定场景时,我确实尝试了一些提到的使用 mockito 的技术,但我无法找到我的用例的解决方案。这是我的场景:
我有一个方法 A(对数据进行本地处理)和一个方法 B(对数据进行一些远程处理)。方法 A 依次调用我的方法 B。我想调用方法 A,当它依次调用方法 B 时,我想 return 来自方法 B 的预定义值,让我们说一个文件列表。这是来自测试 class 和实际 class:
的示例代码
Myclass mc = Mockito.mock(MyClass.class);
when(mc.methodB(param1,param2)).thenReturn(fileSet); // returns mocked fileSet (set of files)
when(mc.methodA(param1,param2)).thenCallRealMethod(); //calls real method A
mc.methodA(param1,param2); //does not return the mocked value from methodB
class MyClass{
public Set<File> methodB(param1,param2){
//some processing
return fileSet;
}
public void methodA(param1,param2){
//some processing
Set<FileSet> fileSet = methodB(param1,param2);
//some more processing on returned files
}
}
我创建了我的 class 的模拟,并确保当我调用方法 A 时,会发生对方法 A 的真实方法调用,而当我调用方法 B 时,模拟结果是 returned。
如果我分别测试方法 A 和方法 B,它可以工作,但是当我调用方法 A 而后者又调用方法 B 时,它不会 return 我从方法 B 中模拟的值。
这不是进行此调用的正确方法还是我遗漏了什么?
如果我理解正确,您想从 class 模拟一个方法,而实际上从同一个 class.
调用另一个方法
这可以使用 spies 来完成:对于间谍,对象中的每个方法都会被真正调用,除非它被明确地存根:
MyClass myClass = new MyClass();
MyClass spy = spy(myClass); // creates a spy for myClass
doReturn(new HashSet<File>() {{ add(new File("file1")); }}).when(spy).methodB("", ""); // stubbing method B
spy.methodA(param1, param2); // calling the real method A
请注意,间谍应谨慎使用,仅用于处理您无法更改的遗留代码。
请注意,存根 methodB
的结构不同于 "usual" 的结构。如果我们编写如下代码:
when(spy.methodB("", "")).thenReturn(...);
正在发生的事情是真正的 methodB
在这里被调用,这是我们不想要的。在第二个构造中:
doReturn(...).when(spy).methodB("", "");
未调用methodB
。
这是一个完整的测试 class 演示间谍:
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
public class TestClass {
@Test
public void test() {
MyClass myClass = new MyClass();
MyClass spy = spy(myClass); // creates a spy for myClass
doReturn(new HashSet<File>() {{ add(new File("file1")); }}).when(spy).methodB("", ""); // stubbing method B
spy.methodA("", ""); // calling the real method A
}
}
class MyClass {
public Set<File> methodB(String param1, String param2) {
return new HashSet<File>() {{ add(new File("file2")); }};
}
public void methodA(String param1, String param2) {
Set<File> fileSet = methodB(param1, param2);
System.out.println(fileSet); // prints [file1] and not [file2], meaning the stubbed method was called and not the real one
}
}
我是 Mockito 的新手,我想为一些遗留代码编写单元测试。在测试我的特定场景时,我确实尝试了一些提到的使用 mockito 的技术,但我无法找到我的用例的解决方案。这是我的场景:
我有一个方法 A(对数据进行本地处理)和一个方法 B(对数据进行一些远程处理)。方法 A 依次调用我的方法 B。我想调用方法 A,当它依次调用方法 B 时,我想 return 来自方法 B 的预定义值,让我们说一个文件列表。这是来自测试 class 和实际 class:
的示例代码Myclass mc = Mockito.mock(MyClass.class);
when(mc.methodB(param1,param2)).thenReturn(fileSet); // returns mocked fileSet (set of files)
when(mc.methodA(param1,param2)).thenCallRealMethod(); //calls real method A
mc.methodA(param1,param2); //does not return the mocked value from methodB
class MyClass{
public Set<File> methodB(param1,param2){
//some processing
return fileSet;
}
public void methodA(param1,param2){
//some processing
Set<FileSet> fileSet = methodB(param1,param2);
//some more processing on returned files
}
}
我创建了我的 class 的模拟,并确保当我调用方法 A 时,会发生对方法 A 的真实方法调用,而当我调用方法 B 时,模拟结果是 returned。
如果我分别测试方法 A 和方法 B,它可以工作,但是当我调用方法 A 而后者又调用方法 B 时,它不会 return 我从方法 B 中模拟的值。
这不是进行此调用的正确方法还是我遗漏了什么?
如果我理解正确,您想从 class 模拟一个方法,而实际上从同一个 class.
调用另一个方法这可以使用 spies 来完成:对于间谍,对象中的每个方法都会被真正调用,除非它被明确地存根:
MyClass myClass = new MyClass();
MyClass spy = spy(myClass); // creates a spy for myClass
doReturn(new HashSet<File>() {{ add(new File("file1")); }}).when(spy).methodB("", ""); // stubbing method B
spy.methodA(param1, param2); // calling the real method A
请注意,间谍应谨慎使用,仅用于处理您无法更改的遗留代码。
请注意,存根 methodB
的结构不同于 "usual" 的结构。如果我们编写如下代码:
when(spy.methodB("", "")).thenReturn(...);
正在发生的事情是真正的 methodB
在这里被调用,这是我们不想要的。在第二个构造中:
doReturn(...).when(spy).methodB("", "");
未调用methodB
。
这是一个完整的测试 class 演示间谍:
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
public class TestClass {
@Test
public void test() {
MyClass myClass = new MyClass();
MyClass spy = spy(myClass); // creates a spy for myClass
doReturn(new HashSet<File>() {{ add(new File("file1")); }}).when(spy).methodB("", ""); // stubbing method B
spy.methodA("", ""); // calling the real method A
}
}
class MyClass {
public Set<File> methodB(String param1, String param2) {
return new HashSet<File>() {{ add(new File("file2")); }};
}
public void methodA(String param1, String param2) {
Set<File> fileSet = methodB(param1, param2);
System.out.println(fileSet); // prints [file1] and not [file2], meaning the stubbed method was called and not the real one
}
}