问题描述
我从Spock单元测试中得到了奇怪的结果,我认为这是由于Groovy的 TupleConstructor
批注.但是,由于另一个用户的帮助,我看到Spock创建模拟的方式存在问题.尽管我已通过用实际实例替换注入的模拟来解决了该问题,但实际上我需要使模拟在这里工作.
I am getting weird results from a Spock unit test that I thought was being caused by a misuse of Groovy's TupleConstructor
annotation. However, thanks to the help of another user, I see it is a problem with the way Spock is creating mocks. Although I have fixed the issue by replacing the injected mocks with real instances, I need to in fact get mocks working here.
我的主要班级:
@Canonical
@TupleConstructor(callSuper = true)
abstract class Vehicle {
Long id
}
@Canonical
@TupleConstructor(callSuper = true, includeSuperProperties = true)
abstract class Foobaz extends Vehicle {
String name
String label
String description
}
@Canonical
@TupleConstructor(callSuper = true, includeSuperProperties = true)
class Fizz extends Foobaz {
// This is an empty class that creates a meaningful name over the
// abstract Foobaz parent class. This may seem like bad design in
// this analogy, but I assure you it makes sense (from a Domain-Driven
// Design perspective) in my actual application.
}
@Canonical
@TupleConstructor(callSuper = true, includeSuperProperties = true)
class Car extends Vehicle {
Fizz fizz1
Fizz fizz2
@Override
String toString() {
"${fizz1.name} - ${fizz2.name}"
}
}
我的Spock测试:
class CarSpec extends Specification {
def "toString() generates a correct string"() {
given: "a Car with some mocked dependencies"
String f1 = 'fizzy'
String f2 = 'buzzy'
Fizz fizz1 = Mock(Fizz)
Fizz fizz2 = Mock(Fizz)
fizz1.name >> f1
fizz2.name >> f2
Car car = new Car(1L, fizz1, fizz2)
when: "we call toString()"
String str = car.toString()
then: "we get a correctly formatted string"
"${f1} - ${f2}" == str
}
}
但是当我运行它时,出现以下失败/错误:
But when I run this I get the following failure/error:
Condition not satisfied:
"${f1} - ${f2}" == str
| | | |
fizzy buzzy | null - null
false
<omitting details here for brevity>
Expected :null - null
Actual :fizzy - buzzy
有什么想法我要去哪里吗?
Any ideas where I'm going awry?
推荐答案
来自我们对@smeeb的问题的另一个讨论中的讨论,我对此进行了更多研究,因为我很困惑为什么它不起作用.
From our discussion on a different one of @smeeb's questions, I looked into this a bit more since I was very confused why this wasn't working.
我创建了自己的测试.
class SomeTest extends Specification {
static class Driver {
String getName(Superclass superclass) {
return superclass.name
}
}
static abstract class Superclass {
String name
}
static class Subclass extends Superclass {
}
def 'test'() {
given:
def driver = new Driver()
def subclass = Mock(Subclass)
subclass.name >> 'test'
expect:
driver.getName(subclass) == 'test'
}
}
它失败了,出现了与@smeeb相同的问题.
It failed with the same problem that @smeeb saw.
driver.getName(subclass) == 'test'
| | | |
| null | false
| Mock for type 'Subclass' named 'subclass'
我尝试更改一些不同的内容,发现当我从 Superclass
中删除 abstract
修饰符或更改了 return superclass.name
时,我发现返回superclass.getName()
测试开始起作用.
I tried changing a few different things and found that when I either removed the abstract
modifier from Superclass
or changed the return superclass.name
to return superclass.getName()
the test began working.
在使用自动生成的访问器从抽象超类继承公共字段之间,在Groovy级别上似乎存在一种怪异的交互作用.
It seems there is a weird interaction on the Groovy-level between getting inherited public fields from an abstract superclass using the auto-generated accessors.
因此,在您的情况下,请从 FooBaz 中删除 abstract
修饰符,或将代码更改为:
So, in your case either remove abstract
modifier from FooBaz
, or change your code to:
@Override
String toString() {
"${fizz1.getName()} - ${fizz2.getName()}"
}
这篇关于Spock Mock无法用于单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!