2012-07-17 65 views
0

我的集成 - 当我尝试使用grails dynamic get方法获取域对象时,我的grails应用程序的测试返回空对象。 这是我的问题的一个简单例子。可以说,我有一个控制器TrackerLogController使用服务TrackerLogService保存另一个跟踪域更新登录域。 域跟踪:在Grails中编写集成测试,用于测试数据库持久性

class Tracker { 

    int id 
    String name 

    static hasMany = [logs: Log] 
} 

域日志:

class Log { 
    int id 
    String comment 

    static belongsTo = [tracker: Tracker] 
} 

控制器TrackerLogController节省:

def TrackerLogService 

def saveTrackerLog() { 

    def trackerId = params.trackerId 

    def trackerInstance = Tracker.get(trackerId) 
    Log log = TrackerLogService.saveTrackerLogs(trackerInstance, params.comment) 
    if(log.hasErrors()){ 
     //render error page 
    } 
    //render good page 
} 

服务TrackerLogService节省:

Log saveTrackerLogs(Tracker tracker, String comment) { 
    Log log = new Log(tracker: tracker, comment: comment) 
    log.save() 
    return log 
} 

所以现在我想为这个服务编写一个集成测试,但我不确定是否应该为控制器中的简单逻辑编写一个(如果错误,错误页面其他好页面)我想我会写一个单元测试以及用于检查数据库中的持久性的Integration-Test。

这就是我对我的集成测试:

class TrackerLogServiceTests { 

    def trackerLogService 

    @Before 
    void setUp(){ 

     def tracker = new Tracker(id: 123, name: "First") 

     tracker.save() 

     //Now even if I call Tracker.get(123) it will return a null value... 
    } 

    @Test 
    void testTrackerLogService() { 
     Tacker trackerInstance = Tracker.get(123) //I have tried findById as well 

     String commit = "This is a commit" 

     //call the service 
     Log log = trackerLogService.saveTrackerLogs(trackerInstance , commit) 

     //want to make sure I added the log to the tracker Instance 
     assertEquals log , trackerInstance.logs.findByCommit(commit) 
    } 
} 

因此,对于这个例子我trackerInstance将是一个空对象。我知道Grails的魔法对于没有Mocking的单元测试似乎不起作用,我认为在数据库中持久化的整合测试可以使用Grails魔法。

回答

3

除非声明它是“分配的”,否则不能指定id值。因为它现在使用自动增量,所以你的123值不被使用。它实际上是由地图构造出于安全原因被忽略,所以你需要这样做:

def tracker = new Tracker(name: "First") 
tracker.id = 123 

,但随后会被自动递增查找得到覆盖。使用此方法代替:

class TrackerLogServiceTests { 

    def trackerLogService 

    private trackerId 

    @Before 
    void setUp(){  
     def tracker = new Tracker(name: "First") 
     tracker.save() 
     trackerId = tracker.id 
    } 

    @Test 
    void testTrackerLogService() { 
     Tacker trackerInstance = Tracker.get(trackerId) 

     String commit = "This is a commit" 

     //call the service 
     Log log = trackerLogService.saveTrackerLogs(trackerInstance , commit) 

     //want to make sure I added the log to the tracker Instance 
     assertEquals log , trackerInstance.logs.findByCommit(commit) 
    } 
} 

此外,无关 - 不声明id场,除非它是一个非标准的类型,例如一个字符串。 Grails补充说,对于你来说,还有version字段。所有你需要的是

class Tracker { 
    String name 
    static hasMany = [logs: Log] 
} 

class Log { 
    String comment 
    static belongsTo = [tracker: Tracker] 
} 
+0

非常感谢我的问题帮助!甜美!我现在正在我的测试方法中得到我的trackerInstance,这正是我所要求的..但由于某种原因,当试图调用saveTrackerLogs我得到“无法调用空对象”,这意味着我的trackerLogService为空..我是否需要创建一个新的trackerLogService一些方法(grails服务会受到测试的影响)?或者通过控制器调用它会更容易吗? – PJT 2012-07-17 19:51:47

+0

或嗯..我不知道我是否应该问我的问题不同..我有一个数据库完整的跟踪器,我想真正在数据库上测试它,例如在我的测试类的无效setUp()拉一个跟踪器。得到(“foo”)已经在数据库中没有创建一个全新的跟踪器......也许我应该写一个与此相关的另一个问题。 – PJT 2012-07-17 20:13:15

+0

是的 - 最好问一个问题每个问题 – 2012-07-17 20:14:30