【问题标题】:Mock criteria count api grails/groovy模拟标准计数 api grails/groovy
【发布时间】:2013-04-24 15:46:22
【问题描述】:

我在尝试对服务类 api 进行单元测试时遇到问题

MyService.groovy

public int myMethod() {
  def cr = MyDomain.createCriteria()

  def myDomainCount = cr.count {
    isNull("column1")
  }

  return myDomainCount
}

MyTestClass.groovy

class MyTestClassTests extends GrailsUnitTestCase {

  void testMyCount() {

    mockDomain(MyDomain)

    myCriteria = [count :{Closure cls -> 10}]
    MyDomain.metaClass.static.createCriteria = {myCriteria}

    int cnt = new MyService().myMethod()

    assert 10 == cnt
  }
}

执行 myMethod() 时执行上述测试方法失败。失败就行了

cr.count {
  isNull("column1")
}

我在执行过程中得到的堆栈跟踪:

groovy.lang.MissingMethodException: No signature of method: com.MyService.isNull() is applicable for argument types: (java.lang.String) values: [column1]
 Possible solutions: findAll(), findAll(groovy.lang.Closure), is(java.lang.Object), isCase(java.lang.Object) at
 org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55) at 
 org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:78) at
 org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)

注意:如果我在两个地方(服务类和测试类)都使用cr.list,则相同的测试用例可以正常工作。我不知道为什么它在计数期间失败??????!!!!!!

任何想法都会有很大帮助。在此先感谢。

【问题讨论】:

  • 什么版本的grails?
  • 我正在使用 grails 2.2.0

标签: grails groovy mocking


【解决方案1】:

解决这个问题的两种方法:

1 - 只需创建实例

由于您可以模拟您的域类,因此创建与您的服务查询匹配的实例。

@TestFor(MyService)
@Mock(MyDomain)
class MyServiceTests {
  void testService() {
    MyDomain instance = new MyDomain(...)
    assert instance.save(flush:true)
    def count = service.myMethod()
    assert 1 == count
  }
}

2 - 模拟 grails.gorm.CriteriaBuilder

createCriteria()返回一个grails.gorm.CriteriaBuilder的实例,你可以使用Groovy的MockFor来改变count{}的行为。

@TestFor(MyService)
@Mock(MyDomain)
class MyDomainServiceTests {

  void testWithGroovyMock() {
    def mockedCriteria = new MockFor(CriteriaBuilder)
    mockedCriteria.demand.count(0..999) { Closure cls ->
      return 10
    }

    def count

    mockedCriteria.use {
      count = service.countWithIsNull()
    }

    assert 10 == count

  }

}

您可以找到有关 Groovy MockFor here 的更多信息。

还请注意,我使用 Grails 2.x 声明单元测试(注释)的方式。

【讨论】:

  • 谢谢米歇尔斯...我尝试了你建议的方式。下面是我的代码
  • void testMyServiceMethod() { // 模拟域对象 mockDomain(MyDomain) def mockedCriteria = new MockFor(CriteriaBuilder) mockedCriteria.demand.count(1..1) { Closure cls -> return 10 } def count mockedCriteria.use { count = service.myServiceMethod() } assert 10 == count }
  • 我得到的错误是:groovy.lang.MissingMethodException: No signature of method: com.domain.MyDomain.createCriteria() is applicable for argument types: () values: [] 可能的解决方案: createCriteria() 在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) 在 java.lang。 reflect.Constructor.newInstance(Constructor.java:513)
  • 您是否已将测试更改为使用@TestFor@Mock?我在这里使用 Grails 2.2.1 进行了测试,它可以工作。
  • 我使用 mockDomain(MyDomain) 而不是 @Mock 并扩展了 GrailsUnitTestCase.Does,这会有所不同。为什么我这样做是因为还有其他使用 mockDomain(MyDomain, [instance list]) 的测试用例,我使用 MyDomain.list() 构建一些东西并测试一些其他功能。
猜你喜欢
  • 1970-01-01
  • 2012-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-22
  • 2019-06-25
  • 2012-07-28
相关资源
最近更新 更多