为什么不使用 Grails 3.2 为单元测试注入 sessionFactory?
Why is sessionFactory not injected for unit test using Grails 3.2?
我 运行 遇到一个问题,扩展 HibernateSpec 的单元测试因 sessionFactory
未注入被测服务而失败。每当在测试期间调用 sessionFactory
上的方法时,我都会得到 NullPointerException
(例如 java.lang.NullPointerException: Cannot invoke method getClassMetadata() on null object
),随后测试失败。
我正在使用 Grails 3.2.4 和 Hibernate 5。
这在测试使用 @TestMixin(HibernateTestMixin)
时有效,但看起来有些更新,mixin 已被弃用,建议改用 HibernateSpec
。
这是我的测试片段:
class TestDatabaseServiceSpec extends HibernateSpec {
def setup() {
}
def cleanup() {
}
void "test method"() {
when:
service.method()
then:
true
}
}
这里是被测服务的一个片段:
void method() {
...
TABLE_NAMES.add(sessionFactory.getClassMetadata('MyDomain').tableName)
...
}
我曾尝试在 setup
方法中设置 service.sessionFactory
以及在测试中使用 sessionFactory
方法设置 setupSpec
方法,但不幸的是,这没有帮助。我考虑过使用集成测试,但我真的很想看看我是否可以继续让这个单元测试像以前一样工作。有谁知道我是不是做错了什么,或者是否有 workaround/solution?
谢谢!
查看 HibernateSpec
的源代码可以提供一些提示。可能是您正在使用的 Hibernate 5 grails 插件中没有 getSessionFactory()
方法。
我将 org.grails.plugins:hibernate5:6.0.6
与 grails 3.2.5 一起使用,并且在单元测试中 sessionFactory 对我来说不为空。
我知道并非总是可以升级,但它可以让您了解问题的根源。
更新:
service.sessionFactory = sessionFactory
也必须在测试设置中调用。
对我有用的是在规范中添加注解 @FreshRuntime
并在为我设置 sessionFactory
的测试中添加 doWithSpring
闭包(即 sessionFactory( InstanceFactoryBean、sessionFactory、SessionFactory))。另外,我确保将 service.sessionFactory = sessionFactory
和 service.transactionManager = transactionManager
添加到 setupSpec
方法中。最后,我需要覆盖 getDomainClasses()
以使用我想要在测试中使用的所有域对象。感谢大家的帮助!
自 3.2.3 以来,新特性的测试混合已被弃用。
https://docs.grails.org/latest/guide/testing.html
Since Grails 3.3, the Grails Testing Support Framework is used for all
unit tests. This support provides a set of traits.
但是,我仍然发现自己在使用 HibernateSpec,因为我可以从中获得多个域 classes,以及服务的 ServiceUnitTest。 HibernateSpec 具有所需的 sessionFactory。
例如
class MyServiceSpec extends HibernateSpec implements ServiceUnitTest<MyService>{
List<Class> getDomainClasses() { [Tag, TagLink, TagLinkValue, TagValue, TestDomain] }
...
def setup() {
service.sessionFactory = sessionFactory
...
}
// tests here with all those domain classes available and the service
}
DataTest 允许多个域 classes,但服务也不允许。
https://testing.grails.org/latest/guide/index.html#unitTestingDomainClasses
服务测试允许服务,但不允许多个域 classes。
https://testing.grails.org/latest/guide/index.html#unitTestingServices
您可以同时使用它们,但它们都没有会话工厂(我可以看到),我使用的是 Grails 4.0.1。我查看了最新的 Github 代码,但仍然看不到它可用。另外,DataTest 不是休眠会话,而是使用 SimpleMap,因此您不能将 hql 与它一起使用,这是我想要的。
我的服务使用的是 statelessSession
def statelessSession = sessionFactory.openStatelessSession()
String queryString = "select DISTINCT(t.tagRef) from com.fmr.aps.taggable.TagLink t group by t.tagRef order by t.tagRef ASC"
Query query = statelessSession.createQuery(queryString)
query.setReadOnly(true);
ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY);
所以我需要一个单元测试特征或基础class,我花了几个小时试图让新特征给我想要的东西。甚至我开始对 DataTest class 进行子class 尝试让它给我 sessionFactory,但最终还是使用 HibernateSpec
并且很高兴能够 运行该测试 class 具有多个域、服务和 sessionFactory。
我 运行 遇到一个问题,扩展 HibernateSpec 的单元测试因 sessionFactory
未注入被测服务而失败。每当在测试期间调用 sessionFactory
上的方法时,我都会得到 NullPointerException
(例如 java.lang.NullPointerException: Cannot invoke method getClassMetadata() on null object
),随后测试失败。
我正在使用 Grails 3.2.4 和 Hibernate 5。
这在测试使用 @TestMixin(HibernateTestMixin)
时有效,但看起来有些更新,mixin 已被弃用,建议改用 HibernateSpec
。
这是我的测试片段:
class TestDatabaseServiceSpec extends HibernateSpec {
def setup() {
}
def cleanup() {
}
void "test method"() {
when:
service.method()
then:
true
}
}
这里是被测服务的一个片段:
void method() {
...
TABLE_NAMES.add(sessionFactory.getClassMetadata('MyDomain').tableName)
...
}
我曾尝试在 setup
方法中设置 service.sessionFactory
以及在测试中使用 sessionFactory
方法设置 setupSpec
方法,但不幸的是,这没有帮助。我考虑过使用集成测试,但我真的很想看看我是否可以继续让这个单元测试像以前一样工作。有谁知道我是不是做错了什么,或者是否有 workaround/solution?
谢谢!
查看 HibernateSpec
的源代码可以提供一些提示。可能是您正在使用的 Hibernate 5 grails 插件中没有 getSessionFactory()
方法。
我将 org.grails.plugins:hibernate5:6.0.6
与 grails 3.2.5 一起使用,并且在单元测试中 sessionFactory 对我来说不为空。
我知道并非总是可以升级,但它可以让您了解问题的根源。
更新:
service.sessionFactory = sessionFactory
也必须在测试设置中调用。
对我有用的是在规范中添加注解 @FreshRuntime
并在为我设置 sessionFactory
的测试中添加 doWithSpring
闭包(即 sessionFactory( InstanceFactoryBean、sessionFactory、SessionFactory))。另外,我确保将 service.sessionFactory = sessionFactory
和 service.transactionManager = transactionManager
添加到 setupSpec
方法中。最后,我需要覆盖 getDomainClasses()
以使用我想要在测试中使用的所有域对象。感谢大家的帮助!
自 3.2.3 以来,新特性的测试混合已被弃用。 https://docs.grails.org/latest/guide/testing.html
Since Grails 3.3, the Grails Testing Support Framework is used for all unit tests. This support provides a set of traits.
但是,我仍然发现自己在使用 HibernateSpec,因为我可以从中获得多个域 classes,以及服务的 ServiceUnitTest。 HibernateSpec 具有所需的 sessionFactory。 例如
class MyServiceSpec extends HibernateSpec implements ServiceUnitTest<MyService>{
List<Class> getDomainClasses() { [Tag, TagLink, TagLinkValue, TagValue, TestDomain] }
...
def setup() {
service.sessionFactory = sessionFactory
...
}
// tests here with all those domain classes available and the service
}
DataTest 允许多个域 classes,但服务也不允许。 https://testing.grails.org/latest/guide/index.html#unitTestingDomainClasses
服务测试允许服务,但不允许多个域 classes。 https://testing.grails.org/latest/guide/index.html#unitTestingServices
您可以同时使用它们,但它们都没有会话工厂(我可以看到),我使用的是 Grails 4.0.1。我查看了最新的 Github 代码,但仍然看不到它可用。另外,DataTest 不是休眠会话,而是使用 SimpleMap,因此您不能将 hql 与它一起使用,这是我想要的。
我的服务使用的是 statelessSession
def statelessSession = sessionFactory.openStatelessSession()
String queryString = "select DISTINCT(t.tagRef) from com.fmr.aps.taggable.TagLink t group by t.tagRef order by t.tagRef ASC"
Query query = statelessSession.createQuery(queryString)
query.setReadOnly(true);
ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY);
所以我需要一个单元测试特征或基础class,我花了几个小时试图让新特征给我想要的东西。甚至我开始对 DataTest class 进行子class 尝试让它给我 sessionFactory,但最终还是使用 HibernateSpec
并且很高兴能够 运行该测试 class 具有多个域、服务和 sessionFactory。