如何在 Grails 3 中填充域 类 以进行单元测试
How to populate domain classes in Grails 3 for unit tests
我想知道如何构建域 class 对象的世界以在我的单元测试中使用。什么是最好的方法?
说这是我的代码,ServiceX:
List<Course> getAllCoursesByType(String type) {
List<Course> list = Course.findAllByType(type)
list
}
这是对 ServiceX 的测试:
import grails.buildtestdata.mixin.Build
import grails.test.mixin.TestFor
import grails.test.mixin.Mock
import spock.lang.Specification
@TestFor(ServiceX)
class ServiceXSpec extends Specification {
void "get all open courses"() {
given:
String type = "open"
when:
def list = service.getAllCoursesByType(type)
then:
list.size() == 4
}
}
我怎样才能 "pre populate" test-db(内存)表明我实际上在列表中有 4 个这样的对象?
为此创建集成测试。请参阅示例 here。
这是对何时使用慢速集成测试进行测试的判断要求。关键是测试您的代码,而不是 Grails/hibernate 数据库代码。
大部分服务测试不需要集成测试。我确实认为您需要对具有真实数据库的 运行 系统中的对象交互进行集成测试。我倾向于在使用 GEB 的 GUI 测试中这样做。这些测试通常涵盖基本的端到端场景。这将测试服务器端以及与服务器的 GUI 交互。
在 GUI/GEB 测试中,我没有测试服务的所有排列和边缘条件。我在单元测试中进行了大部分边缘测试。
我发现,对于 Grails,如果一个简单的数据库操作在集成测试中有效,那么大多数其他简单的数据库操作都有效。用于 save()、delete() 等的 Grails 域模拟相当好地模拟了 'real' 数据库操作。 注意:它们都是对内存中的对象进行操作,所以并不完全相同。
我不使用 Spock,但是对于 JUnit,我使用这种方法(仍然适用于 Grails 3):
@TestFor(ServiceX)
@Mock([Course])
class ServiceXTests {
}
@Test
void testXYZ() {
def course= new Course(course: 'ABC')
assert course.save()
. . .
}
Spock 似乎支持此功能。我假设这个域记录的创建属于 Spock 'given' 部分。另请参阅 Grails Testing。
另一个很好的资源是在 Github 上搜索 Grails 源代码。我从他们的例子中学到了很多。
事实证明,您可以向域 类 添加/覆盖方法(例如),如下所示:
import grails.buildtestdata.mixin.Build
import grails.test.mixin.TestFor
import grails.test.mixin.Mock
import spock.lang.Specification
import grails.test.mixin.Mock
@Mock([Course])
@TestFor(ServiceX)
class ServiceXSpec extends Specification {
void "get all open courses"() {
given:
String type = "open"
Course.metaclass.static.findAllByType = { String type -> [new Course()]}
when:
def list = service.getAllCoursesByType(type)
then:
list.size() == 1
}
}
我想知道如何构建域 class 对象的世界以在我的单元测试中使用。什么是最好的方法?
说这是我的代码,ServiceX:
List<Course> getAllCoursesByType(String type) {
List<Course> list = Course.findAllByType(type)
list
}
这是对 ServiceX 的测试:
import grails.buildtestdata.mixin.Build
import grails.test.mixin.TestFor
import grails.test.mixin.Mock
import spock.lang.Specification
@TestFor(ServiceX)
class ServiceXSpec extends Specification {
void "get all open courses"() {
given:
String type = "open"
when:
def list = service.getAllCoursesByType(type)
then:
list.size() == 4
}
}
我怎样才能 "pre populate" test-db(内存)表明我实际上在列表中有 4 个这样的对象?
为此创建集成测试。请参阅示例 here。
这是对何时使用慢速集成测试进行测试的判断要求。关键是测试您的代码,而不是 Grails/hibernate 数据库代码。
大部分服务测试不需要集成测试。我确实认为您需要对具有真实数据库的 运行 系统中的对象交互进行集成测试。我倾向于在使用 GEB 的 GUI 测试中这样做。这些测试通常涵盖基本的端到端场景。这将测试服务器端以及与服务器的 GUI 交互。
在 GUI/GEB 测试中,我没有测试服务的所有排列和边缘条件。我在单元测试中进行了大部分边缘测试。
我发现,对于 Grails,如果一个简单的数据库操作在集成测试中有效,那么大多数其他简单的数据库操作都有效。用于 save()、delete() 等的 Grails 域模拟相当好地模拟了 'real' 数据库操作。 注意:它们都是对内存中的对象进行操作,所以并不完全相同。
我不使用 Spock,但是对于 JUnit,我使用这种方法(仍然适用于 Grails 3):
@TestFor(ServiceX)
@Mock([Course])
class ServiceXTests {
}
@Test
void testXYZ() {
def course= new Course(course: 'ABC')
assert course.save()
. . .
}
Spock 似乎支持此功能。我假设这个域记录的创建属于 Spock 'given' 部分。另请参阅 Grails Testing。
另一个很好的资源是在 Github 上搜索 Grails 源代码。我从他们的例子中学到了很多。
事实证明,您可以向域 类 添加/覆盖方法(例如),如下所示:
import grails.buildtestdata.mixin.Build
import grails.test.mixin.TestFor
import grails.test.mixin.Mock
import spock.lang.Specification
import grails.test.mixin.Mock
@Mock([Course])
@TestFor(ServiceX)
class ServiceXSpec extends Specification {
void "get all open courses"() {
given:
String type = "open"
Course.metaclass.static.findAllByType = { String type -> [new Course()]}
when:
def list = service.getAllCoursesByType(type)
then:
list.size() == 1
}
}