使用@Mock注解的对象是否应该设置详细值?
Should Object using @Mock annotation be set detailed value?
我是 Mockito 的新手,我有一个问题。假设我尝试在我的测试方法中有一个对象实例。我知道我可以使用 @Mock
来拥有它,那是因为我们试图将测试与该对象方法隔离开来。但是,为了控制测试分支,我确实需要在此对象中设置一些值。我应该仍然使用 Mock
还是应该简单地使用新的 Object()
方式来实例化它?还是无所谓(每种方式都可以)?
谢谢。
让我们找出答案,好吗?!
import org.mockito.Mockito;
class Scratch {
public final static String STATIC_CONST = "static const";
private final String JUST_CONST = "private const";
protected String protectedField = "protected field";
String packageProtectedField = null;
public static void main(String[] args) {
Scratch mocked = Mockito.mock(Scratch.class);
System.out.println("static = " + mocked.STATIC_CONST);
System.out.println("const = " + mocked.JUST_CONST);
System.out.println("protected = " + mocked.protectedField);
System.out.println("package = " + mocked.packageProtectedField);
mocked.packageProtectedField = "but now";
System.out.println("updated = " + mocked.packageProtectedField);
}
}
以上打印:
static = static const
const = private const
protected = null
package = null
updated = but now
一些想法:
显然,static const
确实是您所期望的(我使用 mocked.STATIC_CONST
来获取值,但是嘿,它是静态的,所以该值不是来自 mocked
但无论如何从头开始 class 定义)。
有点令人惊讶,至少对我来说,分配 模拟对象的字段实际上有效。但请注意:原始 class 中的赋值仅对 final
字段有效。换句话说:Mockito 做对了,但不是针对非最终字段。
更令人惊讶的是,可以将值存储到模拟中...
但老实说,这些都不重要。你看,在合理的设计中,所有可变字段首先应该是 private。该可变状态代表了对象的绝对核心。 否 外部代码应该处理这些!换句话说:理想情况下,即使您的测试也不关心对象的内部状态(在极少数情况下,使用 package protected getter 方法来访问内部状态以便于验证可能是有意义的,但是那应该是一个罕见的例外)。
除此之外:当你模拟一个对象时,你绝对不应该以任何方式处理那个模拟的字段。你看:那个模拟中的所有 方法 ......它们与你 class 中的原始源代码无关。它们只是:您可以 configure/verify 使用相应的 Mockito 方法的空壳。让它沉入:模拟对象中字段的实际内容无关紧要:因为通常处理这些字段的方法......“不存在”!
所以,长话短说:如图所示,模拟对象可以携带状态。但是正如所解释的那样:您应该完全忽略该方面。使用模拟的唯一正确方法是通过 specifying/verifying 方法调用它们。
最后:我希望 EasyMock、PowerMock(ito) 的行为方式相似。另一方面,当其他模拟框架的实际行为略有不同时,我也不会感到惊讶。我只使用 Mockito 进行了测试,因为恕我直言,在 2018 年,Mockito 是唯一一个在为 JVM 编写单元测试时应该使用的模拟框架。
我是 Mockito 的新手,我有一个问题。假设我尝试在我的测试方法中有一个对象实例。我知道我可以使用 @Mock
来拥有它,那是因为我们试图将测试与该对象方法隔离开来。但是,为了控制测试分支,我确实需要在此对象中设置一些值。我应该仍然使用 Mock
还是应该简单地使用新的 Object()
方式来实例化它?还是无所谓(每种方式都可以)?
谢谢。
让我们找出答案,好吗?!
import org.mockito.Mockito;
class Scratch {
public final static String STATIC_CONST = "static const";
private final String JUST_CONST = "private const";
protected String protectedField = "protected field";
String packageProtectedField = null;
public static void main(String[] args) {
Scratch mocked = Mockito.mock(Scratch.class);
System.out.println("static = " + mocked.STATIC_CONST);
System.out.println("const = " + mocked.JUST_CONST);
System.out.println("protected = " + mocked.protectedField);
System.out.println("package = " + mocked.packageProtectedField);
mocked.packageProtectedField = "but now";
System.out.println("updated = " + mocked.packageProtectedField);
}
}
以上打印:
static = static const
const = private const
protected = null
package = null
updated = but now
一些想法:
显然,static const
确实是您所期望的(我使用 mocked.STATIC_CONST
来获取值,但是嘿,它是静态的,所以该值不是来自 mocked
但无论如何从头开始 class 定义)。
有点令人惊讶,至少对我来说,分配 模拟对象的字段实际上有效。但请注意:原始 class 中的赋值仅对 final
字段有效。换句话说:Mockito 做对了,但不是针对非最终字段。
更令人惊讶的是,可以将值存储到模拟中...
但老实说,这些都不重要。你看,在合理的设计中,所有可变字段首先应该是 private。该可变状态代表了对象的绝对核心。 否 外部代码应该处理这些!换句话说:理想情况下,即使您的测试也不关心对象的内部状态(在极少数情况下,使用 package protected getter 方法来访问内部状态以便于验证可能是有意义的,但是那应该是一个罕见的例外)。
除此之外:当你模拟一个对象时,你绝对不应该以任何方式处理那个模拟的字段。你看:那个模拟中的所有 方法 ......它们与你 class 中的原始源代码无关。它们只是:您可以 configure/verify 使用相应的 Mockito 方法的空壳。让它沉入:模拟对象中字段的实际内容无关紧要:因为通常处理这些字段的方法......“不存在”!
所以,长话短说:如图所示,模拟对象可以携带状态。但是正如所解释的那样:您应该完全忽略该方面。使用模拟的唯一正确方法是通过 specifying/verifying 方法调用它们。
最后:我希望 EasyMock、PowerMock(ito) 的行为方式相似。另一方面,当其他模拟框架的实际行为略有不同时,我也不会感到惊讶。我只使用 Mockito 进行了测试,因为恕我直言,在 2018 年,Mockito 是唯一一个在为 JVM 编写单元测试时应该使用的模拟框架。