【问题标题】:How to populate domain classes in Grails 3 for unit tests如何在 Grails 3 中填充域类以进行单元测试
【发布时间】:2016-06-06 15:29:28
【问题描述】:

我想知道如何构建一个域类对象的世界以在我的单元测试中使用。最好的方法是什么?

说这是我的代码,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
     }

}

我如何“预先填充”test-db(内存)播种我实际上在列表中有 4 个这样的对象?

【问题讨论】:

    标签: unit-testing grails grails-orm spock grails-3.0


    【解决方案1】:

    为此创建集成测试。查看示例here

    【讨论】:

    • 谢谢,您是说大多数服务都应该使用集成测试进行测试吗?有什么办法可以代替它吗?即模拟这个: Course.findAllByType(type)
    • 如果你问我,我会说任何使用数据库的测试都不是一个单元,而是一个集成测试。
    【解决方案2】:

    这是对何时使用慢速集成测试进行测试的判断要求。关键是测试您的代码,而不是 Grails/hibernate DB 代码。

    大部分服务测试不需要集成测试。我确实认为您需要对具有真实数据库的正在运行的系统中的对象交互进行集成测试。我倾向于在使用 GEB 的 GUI 测试中这样做。这些测试通常涵盖基本的端到端场景。这将测试服务器端以及与服务器的 GUI 交互。

    在 GUI/GEB 测试中,我不会测试服务的所有排列和边缘条件。我在单元测试中进行大部分边缘测试。

    我发现使用 Grails,如果一个简单的 DB 操作在集成测试中起作用,那么大多数其他简单的 DB 操作都起作用。用于 save()、delete() 等的 Grails 域模拟相当好地模拟了“真实”数据库操作。 注意:它们确实对内存中的对象进行操作,因此并不完全相同。

    我不使用 Spock,但在 JUnit 中我使用这种方法(仍然适用于 Grails 3):

    @TestFor(ServiceX)
    @Mock([Course])
    class ServiceXTests {
    }
    
    @Test
    void testXYZ() {
      def course= new Course(course: 'ABC')
      assert course.save()
      . . . 
    }
    

    Spock 似乎支持这一点。我会假设这种域记录的创建属于 Spock 的“给定”部分。另请参阅Grails Testing

    另一个很好的资源是在Github 上搜索 Grails 源。我从他们的例子中学到了很多。

    【讨论】:

      【解决方案3】:

      事实证明,您可以向域类添加/覆盖方法(例如),如下所示:

      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
       }
      

      }

      【讨论】:

        猜你喜欢
        • 2017-05-17
        • 2016-01-31
        • 2016-02-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多