Japanese Unit Testing

Last updated by admin 3 years ago

??????? {excerpt:hidden=true}Unit Testing {excerpt}

{excerpt:hidden=true} Grails also supports functional testing. {excerpt} Grails???????????????????????

test suite?????? {excerpt:hidden=true}Creating & Running a test suite {excerpt}

{excerpt:hidden=true} To create a test suite run the "grails create-test-suite" target or just create a new class in "%PROJECT_HOME%grails-test" that extends GroovyTestCase and ends with "Tests". {excerpt} test suite??????????"grails create-test-suite"????????????GroovyTestCase?????"Test"????????????????? "%PROJECT_HOME%grails-test"?????????????

{excerpt:hidden=true} Below is an example of a test suite that tests the validate method on a domain class: {excerpt} ????????????validate?????????????test suite????:

class BookTests extends GroovyTestCase {

def testValid() { def b = new Book(title:"Groovy in Action", author:"Dierk Koenig")

assert b.validate() } }

{excerpt:hidden=true} To run the test suite run the command "grails test-app" {excerpt} test suite?????????"grails test-app"????????????

{excerpt:hidden=true} For more info on how to write unit tests using Groovy see the section on Unit Testing on the main Groovy website. This page contains a useful list of all the different assert methods that come with the JUnit and GroovyTestCase superclasses.{excerpt} Groovy?????????????????????????Groovy website?Unit Testing???????????????? ????????JUnit?GroovyTestCase?????????????????assert?????????????????

Hibenate????????????? {excerpt:hidden=true}Keeping the Hibenate session open {excerpt}

You may find that if you are testing your persisted domain model objects and accessing collection properties that you get hibernate errors. For example, say I'm writing a social bookmarking application and I have a User model object which relates to many UserBookmark objects. (So my User class defines a "Set userBookmarks" property.)

I want to unit test business logic in my User class, so I start out with the following test:

/** 
* Tests saveBookmark 
*/ 
void testSaveBookmark() { 
// verify boris has no bookmarks yet 
def user = User.get(3) 
assertNotNull user 
assertEquals "boris", user.username 
assertEquals 0, user.userBookmarks.size() 
}

But when I run it I get:

[java] 1) testSaveBookmark(UserTests)org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: User.userBookmarks, no session or session was closed 
[java] at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358) 
[java] at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350) 
[java] at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:97) 
[java] at org.hibernate.collection.PersistentSet.size(PersistentSet.java:114) 
[java] at gjdk.org.hibernate.collection.PersistentSet_GroovyReflector.invoke(Unknown Source) 
[java] at groovy.lang.MetaMethod.invoke(MetaMethod.java:111) 
[java] at org.codehaus.groovy.runtime.MetaClassHelper.doMethodInvoke(MetaClassHelper.java:657) 
[java] at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:350) 
[java] at org.codehaus.groovy.runtime.Invoker.invokeMethod(Invoker.java:146) 
[java] at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:104) 
[java] at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.java:85) 
[java] at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeNoArgumentsMethod(ScriptBytecodeAdapter.java:175) 
[java] at UserTests.testSaveBookmark(UserTests.groovy:47) 
[java] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
[java] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
[java] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
[java] at org.codehaus.groovy.grails.support.GrailsTestSuite.runTest(GrailsTestSuite.java:47) 
[java] at grails.util.RunTests.main(RunTests.java:57)

The error is caused by this line:

assertEquals 0, user.userBookmarks.size()

because I'm accessing a collection property on my user object. (Behind the scenes, Hibernate has created a placeholder object for the "userBookmarks" property. The idea is that the data is only fetched when required.)

This works fine in a normal running Grails application because Grails uses the standard "Open Session in View" pattern and support classes provided by Spring, but fails in the test because the same principle is not applied.

The solution is to create a Hibernate session before the test starts and close it after the test finishes.

You can use the setUp() and tearDown() methods (which run before and after each test method, respectively), like so:

import org.hibernate.Session 
import org.hibernate.SessionFactory 
import org.springframework.orm.hibernate3.SessionFactoryUtils 
import org.springframework.orm.hibernate3.SessionHolder 
import org.springframework.transaction.support.TransactionSynchronizationManager

/** * Tests my User code */ class UserTests extends GroovyTestCase {

SessionFactory sessionFactory

void setUp() { Session session = SessionFactoryUtils.getSession(sessionFactory, true) TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session)) }

void tearDown() throws Exception { SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory) SessionFactoryUtils.closeSessionIfNecessary(sessionHolder.getSession(), sessionFactory) }

/** * Tests saveBookmark */ void testSaveBookmark() { // verify boris has no bookmarks yet def user = User.get(3) assertNotNull user assertEquals "boris", user.username assertEquals 0, user.userBookmarks.size() } }

It now passes!

Note the line

SessionFactory sessionFactory

This is set automatically by Grails, so you don't have to look it up yourself!

Credit goes to the following link for code http://forum.hibernate.org/viewtopic.php?t=929167