GriffonUnitTestCase.groovy
01 /*
02  * Copyright 2008-2012 the original author or authors.
03  *
04  * Licensed under the Apache License, Version 2.0 (the "License");
05  * you may not use this file except in compliance with the License.
06  * You may obtain a copy of the License at
07  *
08  *      http://www.apache.org/licenses/LICENSE-2.0
09  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package griffon.test
17 
18 import griffon.core.UIThreadManager
19 
20 /**
21  * Support class for writing unit tests in Griffon. It mainly provides
22  * access to various mocking options, while making sure that the meta-
23  * class magic does not leak outside of a single test.
24  * It also provides access to the threading facilities exposed by
25  * {@code UIThreadManager}.
26  */
27 class GriffonUnitTestCase extends GroovyTestCase {
28     Map savedMetaClasses
29 
30     protected void setUp() {
31         super.setUp()
32         savedMetaClasses = [:]
33     }
34 
35     protected void tearDown() {
36         super.tearDown()
37 
38         // Restore all the saved meta classes.
39         savedMetaClasses.each clazz, metaClass ->
40             GroovySystem.metaClassRegistry.removeMetaClass(clazz)
41             GroovySystem.metaClassRegistry.setMetaClass(clazz, metaClass)
42         }
43     }
44 
45     /**
46      * Use this method when you plan to perform some meta-programming
47      * on a class. It ensures that any modifications you make will be
48      * cleared at the end of the test.
49      @param clazz The class to register.
50      */
51     protected void registerMetaClass(Class clazz) {
52         // If the class has already been registered, then there's nothing to do.
53         if (savedMetaClasses.containsKey(clazz)) return
54 
55         // Save the class's current meta class.
56         savedMetaClasses[clazz= clazz.metaClass
57 
58         // Create a new EMC for the class and attach it.
59         def emc = new ExpandoMetaClass(clazz, true, true)
60         emc.initialize()
61         GroovySystem.metaClassRegistry.setMetaClass(clazz, emc)
62     }
63 
64     /**
65      * Creates a new Griffon mock for the given class. Use it as you
66      * would use MockFor and StubFor.
67      @param clazz The class to mock.
68      @param loose If <code>true</code>, the method returns a loose-
69      * expectation mock, otherwise it returns a strict one. The default
70      * is a strict mock.
71      */
72     protected GriffonMock mockFor(Class clazz, boolean loose = false) {
73         registerMetaClass(clazz)
74         return new GriffonMock(clazz, loose)
75     }
76 
77     /** Executes code synchronously inside the UI thread */
78     def execSync = UIThreadManager.instance.&executeSync
79     /** Executes code asynchronously inside the UI thread */
80     def execAsync = UIThreadManager.instance.&executeAsync
81     /** Executes code outside the UI thread */
82     def execOutside = UIThreadManager.instance.&executeOutside
83     /** True if the current thread is the UI thread */
84     def isUIThread = UIThreadManager.instance.&isUIThread
85     /** Schedules a block of code as a Future */
86     def execFuture = Object... args ->
87         UIThreadManager.instance.executeFuture(* args)
88     }
89 }