Я пытаюсь динамически изменять и добавлять методы класса, определенного в скрипте groovy, из другого скрипта groovy, но не могу понять, почему он работает, если я использую имя класса непосредственно в .metaClass. но не, если я загружаю класс с помощью GroovyClassLoader (что мне нужно сделать!).
В одном файле 'MyTest.groovy' у меня есть
class MyTest {
public void setUp() {
println "SET UP"
}
public void tearDown() {
println "TEAR DOWN"
}
public void testA() {
println "testA"
}
}
и другой файл 'suite.groovy' содержит
#!/usr/bin/env groovy
public class MyTestSuite {
// For debug
public static printClassLoader(Class cls) {
ClassLoader loader = cls.classLoader
while (loader) {
println loader.class
println loader.URLs.join("\n")
println "\n\n"
loader = loader.parent
}
}
public static void suite() {
// First method to define my class (change/addition of methods works)
//Class testClass = MyTest
// Second way to define my class (change/addition of methods doesn't work)
ClassLoader parent = MyTestSuite.class.getClassLoader();
GroovyClassLoader gcl = new GroovyClassLoader(parent);
Class testClass = gcl.parseClass(new File("MyTest.groovy"));
printClassLoader(testClass)
testClass.metaClass.setUp = {-> println "I'm your new setUp()" ;}
testClass.metaClass.newTest = {-> println "I'm your new newTest()" ; }
}
}
MyTestSuite.suite()
MyTest aTest = new MyTest()
aTest.setUp()
aTest.newTest()
При первом способе я получаю ожидаемый результат:
I'm your new setUp()
I'm your new newTest()
Но со вторым я получаю
SET UP
Caught: groovy.lang.MissingMethodException: No signature of method: MyTest.newTest() is applicable for argument types: () values: []
Possible solutions: testA(), getAt(java.lang.String), wait(), inspect(), every()
at suite.run(suite.groovy:34)
Интересно, что изменение существующего метода не работает, но нет исключения, но попытка добавить новый выдает один.
Я считаю, что это связано с используемыми загрузчиками классов, но я не мог понять, что именно и что изменить!
Для первой версии здесь представлены загрузчики классов:
class groovy.lang.GroovyClassLoader$InnerLoader
class groovy.lang.GroovyClassLoader
class org.codehaus.groovy.tools.RootLoader
class sun.misc.Launcher$AppClassLoader
class sun.misc.Launcher$ExtClassLoader
Для второй версии:
class groovy.lang.GroovyClassLoader$InnerLoader
class groovy.lang.GroovyClassLoader
class groovy.lang.GroovyClassLoader$InnerLoader
class groovy.lang.GroovyClassLoader
class org.codehaus.groovy.tools.RootLoader
class sun.misc.Launcher$AppClassLoader
class sun.misc.Launcher$ExtClassLoader
Любая идея приветствуется!
Franck