Java 模拟内部最终对象
我正在尝试为预先存在的类编写一个测试Java 模拟内部最终对象,java,unit-testing,mocking,mockito,Java,Unit Testing,Mocking,Mockito,我正在尝试为预先存在的类编写一个测试 class ClassToBeTested { private final Obj1 a; ClassToBeTested(String anotherVariable) { a = new Obj1(anotherVariable); } public void methodToBeTested() { if(invokeSomeOtherMethod()) { a.getAnotherVar
class ClassToBeTested {
private final Obj1 a;
ClassToBeTested(String anotherVariable) {
a = new Obj1(anotherVariable);
}
public void methodToBeTested() {
if(invokeSomeOtherMethod()) {
a.getAnotherVariable().doSomething();
}
}
public boolean invokeSomeOtherMethod() {
// return true or false based on some logic
}
Obj1 getObj1() {
return a;
}
}
下面是我的测试课:
class TestClass {
@Test
public void testMethod() {
ClassToBeTested x = new ClassToBeTested("someString");
ClassToBeTested spyX = spy(x);
doReturn(false).when(spyX).invokeSomeOtherMethod();
spyX.methodToBeTested();
verify(spyX, times(1)).getObj1().doSomething();
}
}
这是我的理解:
由于obj1是在类构造函数中创建的私有最终对象,因此不能在测试方法中直接访问它,也不能强制spyObject使用obj1的模拟版本
另外,由于verify()需要模拟版本的obj1,因此它会向我抛出一个错误:
需要但未调用:x.getObj1(),但是与此模拟存在其他交互:x.invokeSomeOtherMethod()
我的理解错了吗?测试testMoethod()的方法是什么?您似乎不知道如何正确地进行依赖项注入。为了使测试更容易,您不需要更改所有代码-只需使用构造函数伸缩,例如:
class ClassToBeTested {
private final Obj1 a;
public ClassToBeTested(String anotherVariable) {
this(new Obj1(anotherVariable));
}
ClassToBeTested(Obj1 a) {
this.a = a;
}
完成了。现在您有了一个受包保护的构造函数,可以使用它直接插入a的实例。所有其他生产代码都可以保持原样
换句话说:不要使用模拟框架技巧“修复”您的设计问题 修改构造函数以便注入
a
?我希望避免这种情况,因为它需要在项目中的多个文件之间进行更改。另外,a的初始化并不直接依赖于调用它的代码,因为另一个变量只是当前未使用的字符串。我不理解您的代码。你的类只显示一个构造函数——没有没有没有参数的构造函数。但是您使用的构造函数在测试方法中没有参数。哪一个是对的?对不起…我的错。。。纠正它。。。有一个带有一个字符串参数的构造函数。您的问题是在spyX
对象上调用verify
,而在Obj1
对象上尝试验证方法调用。可能最简单的方法是添加第二个构造函数,在这里传入一个Obj1
,而不是字符串
。然后在测试中使用第二个构造函数,并传入一个mockObj1
,然后进行验证。