使用构造函数参数模拟嵌套 class 并测试方法
Mock a nested class with constructor parameters and test the methods
我正在尝试模拟具有嵌套 class 的 class。嵌套的 class 带有构造函数参数。
当我尝试使用 mockito 进行测试而不是模拟时,实际的方法正在执行。
我已经在外部 class 上完成了 @InjectMocks,在内部 class 上完成了 @Mock。
//Actual Class to test using Mockito.
public class ClassA {
public void initMethod(String s1, String s2, String s3, String s4) throws Exception {
ClassB objB = null;
if (objB == null && s3 != null && s4 != null && s2 != null) {
SampleUtil.KeyStorePasswordPair pair = SampleUtil.getKeyStorePasswordPair(s3, s4);
objB = new ClassB(s1, s2, pair.keyStore, pair.keyPassword);
try {
objB.meth1(); //Note: meth1 and meth2 are void methods.
objB.meth2(); // These two methods only to be accessed. something like doNothing
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
我像往常一样尝试使用@Mock 调用 class,但正在访问实际方法 meth1()。
//Somthing which I tried
@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {
@InjectMocks
ClassA classA;
@Mock
ClassB classB;
@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testInitClient() throws Exception {
// Setup
// Run the test
classA.initMethod("Lorem", "Ipsum", "TestStr1", "TestStr2");
doNothing().when(classB).meth1(); // This is the line need to be mocked. But instead calling the actual method and executing
// Verify the results
}
需要模拟内部 ClassB 方法,而不是访问真正的方法。
作为 mockito 的初学者,我正在努力解决这个问题。但是在访问 void 方法等几点上感到困惑,所以那时不能使用。使用参数等访问构造函数,
如果没有某种依赖注入,我认为这是不可能的。
在这里,我修改了您的代码,使其按照您的要求运行。
public class ClassA {
// Needed so that it can be replaced with setter
private ClassB objB;
// Extract the generation of ClassB so that it can be prevented
public void generateClassB(String s1, String s2) {
this.objB = new ClassB(s1, s2);
}
public void initMethod(String s1, String s2, String s3, String s4) {
objB = null;
if (s3 != null && s4 != null && s2 != null) {
SampleUtil.KeyStorePasswordPair pair = SampleUtil.getKeyStorePasswordPair(s3, s4);
generateClassB(s1, s2);
try {
objB.meth1(); //Note: meth1 and meth2 are void methods.
objB.meth2(); // These two methods only to be accessed. something like doNothing
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void setClassB(ClassB classB) {
this.objB = classB;
}
}
这是我为了测试结果而使用的ClassB的实现。
public class ClassB {
private String s1;
private String s2;
public ClassB(String s1, String s2) {
this.s1 = s1;
this.s2 = s2;
}
public void meth1() {
System.out.println(s1);
}
public void meth2() {
System.out.println(s2);
}
}
和测试文件
@RunWith(MockitoJUnitRunner.class)
public class DemoApplicationTests {
private ClassA classA;
private ClassB classB;
@Test
public void testInitClient() {
classA = Mockito.spy(ClassA.class);
classB = Mockito.spy(new ClassB("a", "b"));
Mockito.doNothing()
.when(classB)
.meth1();
// This will replace the ClassA#generateClassB method call with the setter
Mockito.doAnswer(args -> {
classA.setClassB(classB);
return null;
}).when(classA).generateClassB(Mockito.any(), Mockito.any());
classA.initMethod("a", "b", "c", "d");
}
}
另一种更简洁的解决方案是将 ClassB 实例传递给 ClassA#initMethod。
我正在尝试模拟具有嵌套 class 的 class。嵌套的 class 带有构造函数参数。 当我尝试使用 mockito 进行测试而不是模拟时,实际的方法正在执行。
我已经在外部 class 上完成了 @InjectMocks,在内部 class 上完成了 @Mock。
//Actual Class to test using Mockito.
public class ClassA {
public void initMethod(String s1, String s2, String s3, String s4) throws Exception {
ClassB objB = null;
if (objB == null && s3 != null && s4 != null && s2 != null) {
SampleUtil.KeyStorePasswordPair pair = SampleUtil.getKeyStorePasswordPair(s3, s4);
objB = new ClassB(s1, s2, pair.keyStore, pair.keyPassword);
try {
objB.meth1(); //Note: meth1 and meth2 are void methods.
objB.meth2(); // These two methods only to be accessed. something like doNothing
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
我像往常一样尝试使用@Mock 调用 class,但正在访问实际方法 meth1()。
//Somthing which I tried
@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {
@InjectMocks
ClassA classA;
@Mock
ClassB classB;
@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testInitClient() throws Exception {
// Setup
// Run the test
classA.initMethod("Lorem", "Ipsum", "TestStr1", "TestStr2");
doNothing().when(classB).meth1(); // This is the line need to be mocked. But instead calling the actual method and executing
// Verify the results
}
需要模拟内部 ClassB 方法,而不是访问真正的方法。
作为 mockito 的初学者,我正在努力解决这个问题。但是在访问 void 方法等几点上感到困惑,所以那时不能使用。使用参数等访问构造函数,
如果没有某种依赖注入,我认为这是不可能的。
在这里,我修改了您的代码,使其按照您的要求运行。
public class ClassA {
// Needed so that it can be replaced with setter
private ClassB objB;
// Extract the generation of ClassB so that it can be prevented
public void generateClassB(String s1, String s2) {
this.objB = new ClassB(s1, s2);
}
public void initMethod(String s1, String s2, String s3, String s4) {
objB = null;
if (s3 != null && s4 != null && s2 != null) {
SampleUtil.KeyStorePasswordPair pair = SampleUtil.getKeyStorePasswordPair(s3, s4);
generateClassB(s1, s2);
try {
objB.meth1(); //Note: meth1 and meth2 are void methods.
objB.meth2(); // These two methods only to be accessed. something like doNothing
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void setClassB(ClassB classB) {
this.objB = classB;
}
}
这是我为了测试结果而使用的ClassB的实现。
public class ClassB {
private String s1;
private String s2;
public ClassB(String s1, String s2) {
this.s1 = s1;
this.s2 = s2;
}
public void meth1() {
System.out.println(s1);
}
public void meth2() {
System.out.println(s2);
}
}
和测试文件
@RunWith(MockitoJUnitRunner.class)
public class DemoApplicationTests {
private ClassA classA;
private ClassB classB;
@Test
public void testInitClient() {
classA = Mockito.spy(ClassA.class);
classB = Mockito.spy(new ClassB("a", "b"));
Mockito.doNothing()
.when(classB)
.meth1();
// This will replace the ClassA#generateClassB method call with the setter
Mockito.doAnswer(args -> {
classA.setClassB(classB);
return null;
}).when(classA).generateClassB(Mockito.any(), Mockito.any());
classA.initMethod("a", "b", "c", "d");
}
}
另一种更简洁的解决方案是将 ClassB 实例传递给 ClassA#initMethod。