views:

41

answers:

1

I am writing unit test cases for my Service Class. Below is my code in controller:

TuneController

def list = {

}

def listData= {

    playerId="6600AE"
    def tuneInstanceList = new ArrayList<Tune>()


    tuneInstanceList = tuneService.calculateId(String playerId)


    def editResult = [total: tuneInstanceList.size(), items: tuneInstanceList]


    render editResult as JSON;
}

Below is my code in TuneService: The below method is called from listData action. ListData is mentioned in my js file test.js

List<Tune> calculateId(String playerId) {             

   try{
   //read the sql file 
        String playerSql = grailsApplication.mainContext.getResource('classpath:' +         Constants.PLAYER_FILE).inputStream.text 

    def sql = new groovy.sql.Sql(dataSource)                 

    def params = [playerId:playerId] 
    def tuneInstanceList = new ArrayList<Tune>() 

    def results = sql.rows(playerSql, params) 

    tuneInstanceList = results.each { 
        def tune = new Tune() 
        tune.setPlayerId  it.player_id   
        tuneInstanceList.add tune
    }
    return tuneInstanceList

}catch (Exception ex) {
        log.error ex.message, ex
        throw ex
    }
    //finally {
        //sql.close()
    //}
}

PLAYER_FILE.sql has the below data. This file is present in grails-app/sql/PLAYER_FILE.sql

select player_Id from tunes where player_Id=:playerId

Test.js:

Ext.onReady(function(){ 

// create the Data Store 
var ds = new Ext.data.Store({ 
   autoLoad: true, 
   proxy: new Ext.data.HttpProxy({ 
   url: 'http://localhost:8080/music/tune/listData'}), 
   reader: new Ext.data.JsonReader({ 
    results: 'total', 
    root:'items', 
    id:'id' 
   }, 
   [ 
           {name: 'playerId' } 

      ] 
   ) 
}); 

var cm = new Ext.grid.ColumnModel([ 
    {header: "Player Id", width: 120, dataIndex: 'playerId' }, 

]); 
cm.defaultSortable = true; 

// create the grid 
var grid = new Ext.grid.GridPanel({ 
    ds: ds, 
    cm: cm, 
    renderTo:'grid-example', 
    width:540, 
    height:200 
});    });

Below is the test that I wrote for my service class. Here I am getting the missing prperty exception. I believe this is for the line "def sql = new groovy.sql.Sql(dataSource)". This is what is mentioned in the exceptions. Its reg. this sql. Here in my test, I have to mention the datasource or mock the datasource. I am not too sure though.

My test case is below:

void testReturnList() {          
    TuneService tuneService = new TuneService()     
    List tuneList = tuneService.calculateId()  
    assertTrue(tuneList.size()>0)   
} 

groovy.lang.MissingPropertyException: No such property: sql for class: pride.TuneService Possible solutions: log at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:49) at org.codehaus.groovy.runtime.callsite.GetEffectivePogoPropertySite.getProperty(GetEffectivePogoPropertySite.java:86) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:241) at pride.TuneService.calculateId(TuneService.groovy:67) at pride.TuneService$calculateId.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117) at pride.TuneServiceTests.testReturnList(TuneServiceTests.groovy:23) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at junit.framework.TestCase.runTest(TestCase.java:168) at junit.framework.TestCase.runBare(TestCase.java:134) at junit.framework.TestResult$1.protect(TestResult.java:110) at junit.framework.TestResult.runProtected(TestResult.java:128) at junit.framework.TestResult.run(TestResult.java:113) at junit.framework.TestCase.run(TestCase.java:124) at junit.framework.TestSuite.runTest(TestSuite.java:232) at junit.framework.TestSuite.run(TestSuite.java:227) at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

EDITED: Below is the error that I get after commenting sql.close()

java.lang.NullPointerException: Cannot get property 'mainContext' on null object at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:56) at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:156) at org.codehaus.groovy.runtime.callsite.NullCallSite.getProperty (NullCallSite.java:44) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty (AbstractCallSite.java:237) at pride.TuneService.calculateId(TuneService.groovy:37) at pride.TuneService$calculateId.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117) at pride.TuneServiceTests.testReturnList(TuneServiceTests.groovy:23) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at junit.framework.TestCase.runTest(TestCase.java:168) at junit.framework.TestCase.runBare(TestCase.java:134) at junit.framework.TestResult$1.protect(TestResult.java:110) at junit.framework.TestResult.runProtected(TestResult.java:128) at junit.framework.TestResult.run(TestResult.java:113) at junit.framework.TestCase.run(TestCase.java:124) at junit.framework.TestSuite.runTest(TestSuite.java:232) at junit.framework.TestSuite.run(TestSuite.java:227) at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

How do I go about writing this test case. Thoughts?

A: 

I don't think you've given us the right code to help you debug this error. If you examine the stack trace more closely, you'll see where the "missing property" is:

at pride.RecoveryService.calculateImpact(RecoveryService.groovy:67)

Have a look at that line. It's likely that you're referring to a property called sql that hasn't been defined for the method/closure/class.

Edit:

After your update, I see at least one problem:

String sql = grailsApplication.mainContext.getResource('classpath:' + Constants.PLAYER_FILE).inputStream.text 
def sql = new groovy.sql.Sql(dataSource)  

You're defining sql twice here as different types. I only point that out because your stack trace seems to be related to that variable.

Can you point out which line is line in TuneService.groovy is line 67?

Rob Hruska
Also, have a look at http://stackoverflow.com/questions/3988788/what-is-a-stack-trace-and-how-can-i-use-it-to-debug-my-application-errors to see how to read that stack trace.
Rob Hruska
Updated my code. Inputs?
Alex
I had a finally block in my code which read sql.close(). That was the line number 67. Do not know why that was giving an error, because it works fine whne i run the app otherwise. And as u said, I changed the sql def dtaht was defined twice. Now when I run it I get another error which corresponds to line 37 which is String sql = grailsApplication.mainContext.getResource('classpath:' + Constants.PLAYER_FILE).inputStream.text Do u think I have written my tests fine?
Alex
After your update it looks like `grailsApplication` is null in your code. I'm not sure that `grailsApplication` is available to services, and I'm not entirely sure how to access its information otherwise.
Rob Hruska
If I run my application with this code, it runs fine and I get the desired output. Do you think it has something to do with mocking?I mean is it that my Unit tests are unable to access the .sql file in grails-app folder? Do u think my unit tests are missing something?
Alex
Well, if it's a unit test it's doubtful that `grailsApplication` would be available. `grailsApplication` might be available if you were to write the test as an integration test, though. Unit tests don't get any of the dynamic properties that are normally available at runtime.
Rob Hruska
Thanks Rob. Is there any way grailsApplication can be kept available in Unit Tests?
Alex
Well, it wouldn't really make sense. You'd have to mock it out in an unit test. If you need it to exist for your test, you should use an integration test instead, since that's what they're for (providing the application context).
Rob Hruska
Thanks Rob for your inputs. Integration Test seems to be the right way out. I have written the Integration Test and since its a different code , I have put it as a separate question. "Integration Test with JSON output" is the subject Link: http://stackoverflow.com/questions/4020880/integration-test-with-json-output
Alex