在 Mockito 中模拟对象创建的不同方式?
Different ways of mocking object creation in Mockito?
我看到了几种不同的模拟对象的方法。这种使用 InjectMocks 的方法与此处显示的方法之间到底有什么区别:https://github.com/mockito/mockito/wiki/Mocking-Object-Creation?
@ExtendWith(MockitoExtension.class)
public class MyTest() {
@Mock ClassB uut;
@InjectMocks ClassA cA;
@Test
public TestOne() {
...
}
}
哪里
public class ClassA() {
public ClassA() {
ClassB temp = new ClassB();
}
}
与此处显示的方法相比:
https://github.com/mockito/mockito/wiki/Mocking-Object-Creation
到底有什么区别?
我认为这些方法之间没有本质区别。
InjectMocks 方法
实际上,要使其正常工作,您的 class 应该通过构造函数或 setter 接受依赖项(并且永远不能同时使用两者)。我会说这种方法使测试更容易,因为你在初始化阶段将你想要的任何东西注入你的 class 对象。
class Foo {
private final Bar bar;
public Foo(final Bar bar) {
this.bar = bar;
}
}
如果这是我们的 class 测试,那么@InjectMock 所做的就是创建模拟,并执行以下操作:
Foo foo = new Foo(barMock);
除了可测试之外,想象一下如果 Bar
是一个接口,那么您可以在它的多个实现之间切换而无需实际接触 class 代码(理想情况下)。如果你有一个 DI 框架,那就更容易了。所以,基本上 class 的这种格式使其变得灵活。
使用单行方法创建对象
假设这是我们正在测试的 class。如您所见,我正在构造函数中初始化 属性 。从法律上讲,没有反射魔法,我不能在初始化期间或之后放置模拟 bar
变量。
class Foo {
private final Bar bar;
public Foo() {
this.bar = new Bar();
}
}
Mockito 文档告诉您切换到单行方法或工厂助手的原因是:
- Mockito 不能模拟构造函数,这意味着你不能在没有反射的情况下将模拟对象放在
bar
的位置,你只能在初始化之后这样做。一般来说,以我对测试的看法,应该尽量避免反射。
- 单行函数看起来和构造函数一样干净,而且它们可以是描述性的(就像静态工厂方法)。
因此,当您将 class 切换为如下所示时:
class Foo {
private final Bar bar;
public Foo() {
this.bar = makeBar();
}
Bar makeBar() {
return new Bar();
}
}
现在,你可以放置一个间谍,轻松地模拟 makeBar
方法。这同样适用于工厂方法。老实说,工厂方法对我来说看起来有点罗嗦,但我相信有时候它会派上用场。
我看到了几种不同的模拟对象的方法。这种使用 InjectMocks 的方法与此处显示的方法之间到底有什么区别:https://github.com/mockito/mockito/wiki/Mocking-Object-Creation?
@ExtendWith(MockitoExtension.class)
public class MyTest() {
@Mock ClassB uut;
@InjectMocks ClassA cA;
@Test
public TestOne() {
...
}
}
哪里
public class ClassA() {
public ClassA() {
ClassB temp = new ClassB();
}
}
与此处显示的方法相比: https://github.com/mockito/mockito/wiki/Mocking-Object-Creation
到底有什么区别?
我认为这些方法之间没有本质区别。
InjectMocks 方法
实际上,要使其正常工作,您的 class 应该通过构造函数或 setter 接受依赖项(并且永远不能同时使用两者)。我会说这种方法使测试更容易,因为你在初始化阶段将你想要的任何东西注入你的 class 对象。
class Foo {
private final Bar bar;
public Foo(final Bar bar) {
this.bar = bar;
}
}
如果这是我们的 class 测试,那么@InjectMock 所做的就是创建模拟,并执行以下操作:
Foo foo = new Foo(barMock);
除了可测试之外,想象一下如果 Bar
是一个接口,那么您可以在它的多个实现之间切换而无需实际接触 class 代码(理想情况下)。如果你有一个 DI 框架,那就更容易了。所以,基本上 class 的这种格式使其变得灵活。
使用单行方法创建对象
假设这是我们正在测试的 class。如您所见,我正在构造函数中初始化 属性 。从法律上讲,没有反射魔法,我不能在初始化期间或之后放置模拟 bar
变量。
class Foo {
private final Bar bar;
public Foo() {
this.bar = new Bar();
}
}
Mockito 文档告诉您切换到单行方法或工厂助手的原因是:
- Mockito 不能模拟构造函数,这意味着你不能在没有反射的情况下将模拟对象放在
bar
的位置,你只能在初始化之后这样做。一般来说,以我对测试的看法,应该尽量避免反射。 - 单行函数看起来和构造函数一样干净,而且它们可以是描述性的(就像静态工厂方法)。
因此,当您将 class 切换为如下所示时:
class Foo {
private final Bar bar;
public Foo() {
this.bar = makeBar();
}
Bar makeBar() {
return new Bar();
}
}
现在,你可以放置一个间谍,轻松地模拟 makeBar
方法。这同样适用于工厂方法。老实说,工厂方法对我来说看起来有点罗嗦,但我相信有时候它会派上用场。