如何使用Spock测试Grails服务?

10

我有一个名为 EncouragementService.groovy 的文件,其中包含以下方法

  class EncouragementService {
   def stripePaymentService 

   def encourageUsers(List<User> users){
     if(null != users && users.size()>0){
      for(User user : users){
        //logic
        stripePaymentService.encourage(user)
        //
      }
     }   
   }
  }

为了在JAVA环境中测试上述代码,我将首先使用JUnit在setup中创建两个或三个用户。将用户列表传递给encourageUsers(...)方法,并检查我想要的结果。

在grails中,我该如何实现相同的事情?

import com.github.jmkgreen.morphia.Datastore;

@TestFor(EncouragementService)
class EncouragementServiceSpec {

  def morphiaService = new MorphiaService()

  void testEncourageUsers() {
        List<User> users = createUsers();
        encouragementService.(users)  
            //
  }

  def createUsers(){
       Datastore datastore = morphiaService.dataStoreInstance()
       def user = new User()
       user.setName("Prayag Upd")
       //
       datastore.save(user)
       [user]
  }
}

我正在使用spock:0.7

plugins {
    test(":spock:0.7") { exclude "spock-grails-support" }
}
2个回答

13

服务类可以进行以下优化:

class EncouragementService {
   def encourageUsers(List<User> users){
       if(users){ //Groovy truth takes care of all the checks
          for(user in users){
            //logic
          }
       }   
   }
}

Spock单元测试:
Spock将测试提升到了一个全新的层次,您可以测试行为(符合BDD)。测试类将如下所示:

import spock.lang.*

@TestFor(EncouragementService)
@Mock(User) //If you are accessing User domain object.
class EncouragementServiceSpec extends Specification{
  //def encouragementService //DO NOT NEED: mocked in @TestFor annotation

  void "test Encourage Users are properly handled"() {
      given: "List of Users"
          List<User> users = createUsers()

      when: "service is called"
          //"service" represents the grails service you are testing for
          service.encourageUsers(users) 

      then: "Expect something to happen"
          //Assertion goes here
  }

  private def createUsers(){
       return users //List<User>
  }
}

“Patience”是我的名字,我不是在开玩笑。坦白地说,最近我在当地Grails用户组做了一个关于Spock的演讲,所以我想炫耀一下我所做的事情。;) @SérgioMichels - dmahapatro
еҪ“UserдёҚжҳҜеҹәдәҺgrails-app/domainе®һдҪ“ж—¶пјҢжҲ‘дјҡеҫ—еҲ°Failure: test Users are properly handled(np.zazzercode.service.EncouragementServiceSpec) | org.codehaus.groovy.grails.exceptions.GrailsConfigurationException: Cannot add Domain class [class np.zazzercode.domain.User]. It is not a Domain! at grails.test.mixin.domain.DomainClassUnitTestMixin.registerGrailsDomainClass(DomainClassUnitTestMixin.groovy:209)гҖӮ - prayagupa
如果User不是一个领域类,那么你就不需要@Mock,这就是我在答案中的意思。 - dmahapatro
1
@dmahapatro 好的,我明白了。但是我该如何初始化一个服务(例如stripePaymentService),以便在EncouragementService中使用?由于它没有被注入,所以在测试应用程序时会抛出“java.lang.NullPointerException:无法在空对象上调用方法encourage()”。 - prayagupa
2
@dmahapatro 好了,现在修复了,只需在 given 中添加 def stripePaymentService = Mock(StripePaymentService)service.stripePaymentService = stripePaymentService 即可。 - prayagupa
显示剩余2条评论

4
使用build-test-data插件来构建用户。
@TestFor(EncouragementService)
@Build(User)
class EncouragementServiceSpec extends Specification {

  def "encourage users does x"() {
    given:
    def users = createUsers();

    when:
    service.encourageUsers(users)  

    then:
    // assert something
  }

  def createUsers(){
    [User.build(), User.build(), User.build()]
  }
}

我还对代码进行了几处更改,使其变成了一个合适的Spock规范。您的测试必须扩展Specification,并且您可能需要熟悉Spock的关键字


build-test-data插件看起来很棒,但似乎不适用于非grails-app/domain的实体。抛出异常org.codehaus.groovy.grails.exceptions.GrailsConfigurationException: Cannot add Domain class [class np.zazzercode.domain.User]. It is not a Domain - prayagupa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接