如何在单元测试具有带参数的构造函数的 class 时将自动连接的依赖项作为模拟传递
How to pass auto wired dependencies as mock while unit testing a class which has constructors with arguments
我正在尝试对两个单独的 classes 进行单元测试,其中一个的构造函数是默认构造函数,另一个的构造函数是具有一些参数的构造函数。 classes 都有一个自动装配的组件,比如说,
class A {
@Autowired
private SomeClass someClass;
}
class B {
@Autowired
private SomeClass someClass;
public B(int a, String b) {
//method implementation
}
}
我正在尝试对这两个 class 和第一个单元进行单元测试,如果我使用
创建 class 对象
def mockedSomeClass = Mock(SomeClass)
def a = new A(someClass:mockedSomeClass)
它工作正常。
但是对于第二个 class ,我尝试通过不同的语法传递构造函数参数和所需的依赖项
喜欢
def mockedSomeClass = Mock(SomeClass)
def b = new B(10, "g", someClass:mockedSomeClass)
和
def b = new B(someClass:mockedSomeClass, 10, "g")
和
def b = new B(10, "g")(someClass:mockedSomeClass)
所有这些都是反复试验,因为我找不到任何与此特定案例类似的文档。
如能提供有关如何正确执行此操作的任何帮助,我们将不胜感激
提前致谢
在classA中,这样调用构造函数
new A(someClass:mockedSomeClass)
工作正常,因为在 groovy 中,隐式生成的默认构造函数支持通过 passing a named parameter 设置任何字段的值,这仅在默认构造函数中受支持。您有一个字段 (someClass) 已通过构造函数传递,没问题。
但是,在 class B 中,您有一个带有两个参数的显式构造函数。请注意,您只能使用这些指定的两个参数(即 int a、String b)调用此构造函数,因为它是这样明确定义的。请记住,这不是 class A 中的默认构造函数,因此它不会自动支持通过传递命名参数来设置字段。
长话短说,要使其正常工作,您还必须明确指定第三个参数:
class B{
@Autowired
private SomeClass someClass;
public B(int a,String b, SomeClass someClass)
{
//method implementation
this.someClass = someClass;
}
然后你可以这样称呼它:
def b=new B(10, "g", mockedSomeClass)
另一种方法:
上面的方法是我更喜欢的方法,因为它更简洁一些。原因是最好在构造函数中拥有所有强制依赖以避免混淆。
但是,如果由于某些原因您无法更改 Java 源代码,您也可以通过创建对象来解决它:
def b=new B(10, "g")
b.someClass = mockedSomeClass
在上面的例子中,我们首先通过调用class B 的显式构造函数来创建对象,它有两个参数。然后我们设置 someClass 字段(这看起来像手动分配私有字段但实际上我们是通过 groovy 中自动生成的 setter 来设置它,您可以在此处阅读有关隐式 getter 和 setter 的信息:http://groovy-lang.org/style-guide.html#_getters_and_setters)。
我正在尝试对两个单独的 classes 进行单元测试,其中一个的构造函数是默认构造函数,另一个的构造函数是具有一些参数的构造函数。 classes 都有一个自动装配的组件,比如说,
class A {
@Autowired
private SomeClass someClass;
}
class B {
@Autowired
private SomeClass someClass;
public B(int a, String b) {
//method implementation
}
}
我正在尝试对这两个 class 和第一个单元进行单元测试,如果我使用
创建 class 对象def mockedSomeClass = Mock(SomeClass)
def a = new A(someClass:mockedSomeClass)
它工作正常。
但是对于第二个 class ,我尝试通过不同的语法传递构造函数参数和所需的依赖项
喜欢
def mockedSomeClass = Mock(SomeClass)
def b = new B(10, "g", someClass:mockedSomeClass)
和
def b = new B(someClass:mockedSomeClass, 10, "g")
和
def b = new B(10, "g")(someClass:mockedSomeClass)
所有这些都是反复试验,因为我找不到任何与此特定案例类似的文档。
如能提供有关如何正确执行此操作的任何帮助,我们将不胜感激
提前致谢
在classA中,这样调用构造函数
new A(someClass:mockedSomeClass)
工作正常,因为在 groovy 中,隐式生成的默认构造函数支持通过 passing a named parameter 设置任何字段的值,这仅在默认构造函数中受支持。您有一个字段 (someClass) 已通过构造函数传递,没问题。
但是,在 class B 中,您有一个带有两个参数的显式构造函数。请注意,您只能使用这些指定的两个参数(即 int a、String b)调用此构造函数,因为它是这样明确定义的。请记住,这不是 class A 中的默认构造函数,因此它不会自动支持通过传递命名参数来设置字段。
长话短说,要使其正常工作,您还必须明确指定第三个参数:
class B{
@Autowired
private SomeClass someClass;
public B(int a,String b, SomeClass someClass)
{
//method implementation
this.someClass = someClass;
}
然后你可以这样称呼它:
def b=new B(10, "g", mockedSomeClass)
另一种方法:
上面的方法是我更喜欢的方法,因为它更简洁一些。原因是最好在构造函数中拥有所有强制依赖以避免混淆。
但是,如果由于某些原因您无法更改 Java 源代码,您也可以通过创建对象来解决它:
def b=new B(10, "g")
b.someClass = mockedSomeClass
在上面的例子中,我们首先通过调用class B 的显式构造函数来创建对象,它有两个参数。然后我们设置 someClass 字段(这看起来像手动分配私有字段但实际上我们是通过 groovy 中自动生成的 setter 来设置它,您可以在此处阅读有关隐式 getter 和 setter 的信息:http://groovy-lang.org/style-guide.html#_getters_and_setters)。