metaClass.'static' not working when replacing method - groovy

I'm using groovy 1.7.8.
I have the following code:
public class StaticClass {
public static String getStaticString(String string) {
return "NOT WORKING"
}
}
My test:
void testStaticMethod() {
StaticClass.metaClass.'static'.getStaticString = { i ->
"WORKING"
}
assert "WORKING" == StaticClass.getStaticString('test')
}
I can not get my test to pass. Any ideas on what I'm doing wrong?

Try typing the closure:
StaticClass.metaClass.'static'.getStaticString = { String i ->
"WORKING"
}
You need to match the method signature exactly if you're trying to override something.

Related

Non type type parameters

What if I have classes that are different only by some constant used in code. Is it possible to have one generic implementation without runtime cost?
Here is the example (it's a little bit too long...)
#:enum abstract Param(Int) {
var foo = 0;
var bar = 1;
}
class WorkBase {
public function new() {}
private inline function work_impl(p: Param): Void {
if(p == foo) {
trace('foo');
}
else {
trace('bar');
}
}
public function work(): Void {
}
}
class WorkFoo extends WorkBase{
override public function work(): Void {
work_impl(foo);
}
}
class WorkBar extends WorkBase {
override public function work(): Void {
work_impl(bar);
}
}
class Test {
public static function main() {
var workFoo = new WorkFoo();
var workBar = new WorkBar();
workFoo.work();
workBar.work();
}
}
After compilation with -D analyzer-optimize we will see that WorkFoo.work() and WorkBar.work() functions were optimized and contain only one branch of code that matches one of the Param values. In real life there are lot of such comparisons in work_impl(), and they all are optimized out. That's good.
But what if I do not want to create WorkFoo and WorkBar by hand. Is it possible to do something like this:
#:generic
class WorkBase<PARAM> {
private inline function work_impl(p: Param): Void {
...
}
public function work(): Void {
work_impl(PARAM);
}
}
The closest thing I know is const-type-parameter. But I do not feel generic build is a good choice here.
The closest thing I know is const-type-parameter. But I do not feel generic build is a good choice here.
Const type parameters can be used without #:genericBuild - a const type parameter in combination with #:generic is enough to get the desired optimization:
#:enum abstract Param(Int) from Int {
var foo = 0;
var bar = 1;
}
#:generic class Work<#:const PARAM:Int> {
public function new() {}
public function work():Void {
if (PARAM == foo) {
trace('foo');
} else {
trace('bar');
}
}
}
class Main {
public static function main() {
var workFoo = new Work<0>();
var workBar = new Work<1>();
workFoo.work();
workBar.work();
}
}
Due to #:generic, one class is generated for each constant value, for instance on JS the output looks like this:
var Work_$0 = function() {
};
Work_$0.prototype = {
work: function() {
console.log("source/Main.hx:11:","foo");
}
};
var Work_$1 = function() {
};
Work_$1.prototype = {
work: function() {
console.log("source/Main.hx:13:","bar");
}
};
Note that this example fails with a "constraint check failure" in Haxe 3.4.7 for some reason, but works fine with Haxe 4 preview 4 and later. Another limitation is that neither new Work<Param.foo>() nor new Work<foo>() work - you need to pass the actual constant value.

Get the generic type of a List in Groovy

I am building a automated swagger plugin. Here I run through annotated classes.
When we talk about the datatypes of String, Long, etc. is is enough for me use the simpleName method.
But when get to a Class of List, Set, Collection I need to know the generic type.
So how can I do this?
A example of code which do most of the job:
class Foo {
List<String> myString
}
class SomeUtilClass {
static String dataType(Class<?> c) {
return c.simpleName
}
static List<String> dataTypes(Class<?> c) {
return c.metaClass.properties.findAll {MetaProperty metaProperty ->
metaProperty?.field != null
}.collect {dataType(it.type)}
}
}
SomeUtilClass.dataTypes(Foo) // ["List"] but I want something like ["List<String>"]
I found the solution. I can look on the generic type from Cached fields.
See below example:
class SomeUtilClass {
static String dataType(Class<?> c) {
return c.simpleName
}
static List<String> dataTypes(Class<?> c) {
return c.metaClass.properties.findAll {MetaProperty metaProperty ->
metaProperty?.field != null
}.collect {findGenerics(it.type)}
}
static void findGenerics(CachedField t) {
t.field.genericType?.actualTypeArguments.collect {dataType(it)}
}
}

How to use closure to capture the invocation by specific type and ignore others?

I have a mock with a method that can accept all children of an abstract type.In a test,this method may be invoked by different children multiple times,and I want to check that it is invoked by specific type once like this:
1*mockObject.method(_) {SpecificType ct->
//check the ct's field value
}
the problem is that the closure always capture the first invocation due to:
mockObjectt.method(_)
can't distinguish different children types,so it match all invocations,then I tried another way like this:
1*mockObject.method({it instanceof SpecificType}) {SpecificType ct->
//check the ct's field value
}
but the problem of this way is that:
{SpecificType ct->
//Here,any check will return true,
//I think the checkings in here are ignored
}
is ignored always(I think I misused the groovy's closure here)
So question is:
Is there elegant way to capture the invocation by specific child type with specific values and ignore others?
What about: 1*mockObject.method({it instanceof SpecificType && it.field == fieldValue }) ?
Take a look at this sample code:
import spock.lang.Specification
class SimpleTestSpec extends Specification {
private static class A { }
private static class B extends A { }
private static class C extends B { }
private static class D extends A { }
private static class TestClass {
String foo(A value) {
return "A: ${value}"
}
String foo(B value) {
return "B: ${value}"
}
String foo(C value) {
return "C: ${value}"
}
String foo(D value) {
return "D: ${value}"
}
}
private static class ComponentClass {
private final TestClass testClass
ComponentClass(TestClass testClass) {
this.testClass = testClass
}
String foo(A value) {
return testClass.foo(value)
}
}
TestClass testClassMock = Mock(TestClass)
ComponentClass componentClass = new ComponentClass(testClassMock)
def setup() {
testClassMock.foo(_ as D) >> "DDD"
testClassMock.foo(_ as C) >> "CCC"
testClassMock.foo(_ as B) >> "BBB"
testClassMock.foo(_ as A) >> "AAA"
}
def "should use mocked DDD result"() {
when:
String result = testClassMock.foo(new D())
then:
result == "DDD"
}
def "should use mocked CCC result"() {
when:
String result = testClassMock.foo(new C())
then:
result == "CCC"
}
def "should use mocked BBB result"() {
when:
String result = testClassMock.foo(new B())
then:
result == "BBB"
}
def "should use mocked AAA result"() {
when:
String result = testClassMock.foo(new A())
then:
result == "AAA"
}
def "should record invocation based on dynamic type"() {
when:
componentClass.foo(new C())
then:
1 * testClassMock.foo(_ as C)
}
def "should return result associated with mocked invocation in runtime"() {
when:
String result = componentClass.foo(new D())
then:
result == "DDD"
}
}
Gist file: https://gist.github.com/wololock/c59151b67d4c9b0c0c8e
You can specify expected type of an argument using as casting operator. But there is one tricky part - you need to stub class behavior in particular order: from most specific to most general. Try to mix the order in setup() and then you will see that tests will start failing.
You can also make use of Groovy's dynamic method invocation - notice how ComponentClass behaves with injectest TestClass instance which was previously stubbed with expected behavior. You can also count the number of invocations associated with specific type even if external call was made through the most general type method.
I hope it will help you resolve your problem. Best!

How do I intercept calls in Groovy?

I have this class structure:
interface bug
{
def method()
}
public class A implements bug{
def method()
{
println "Works"
}
}
A varaiable = new A()
bug.metaClass.invokeMethod {
name,args ->
println "Came here"
}
varaiable.method()
when I do this, I get Works. Why not Came here?
Where I'm doing the mistake?
EDIT:
Even if I do:
A.metaClass.invokeMethod {
name,args ->
println "Came here"
}
I'm getting only Works.
​
You're changing the metaClass of A with
A.metaClass.invokeMethod { name,args ->
println "Came here"
}
After you construct the variable. If you put this block before the line
A varaiable = new A()
It should work as you'd expect.
To get round this, you can use:
ExpandoMetaClass.enableGlobally()
And instances will check back with the metaClass every invocation, however as expected this can slow things down

Groovy runtime method interception

I'm playing with Groovy and I wonder, why doesn't this piece of code works?
package test
interface A {
void myMethod()
}
class B implements A {
void myMethod() {
println "No catch"
}
}
B.metaClass.myMethod = {
println "Catch!"
}
(new B()).myMethod()
It prints out No catch, while I expect it to print Catch! instead.
It's a bug in Groovy, there is an open issue in JIRA: Cannot override methods via metaclass that are part of an interface implementation, GROOVY-3493.
Instead of rewriting B.metaClass.myMethod, try following:
B.metaClass.invokeMethod = {String methodName, args ->
println "Catch!"
}
This blog post describes it quite well.
There is a workaround but it only applies to all classes and not specific instances.
metaclass modification BEFORE construction:
interface I {
def doIt()
}
class T implements I {
def doIt() { true }
}
I.metaClass.doIt = { -> false }
T t = new T()
assert !t.doIt()
metaclass modification AFTER construction:
interface I {
def doIt()
}
class T implements I {
def doIt() { true }
}
T t = new T()
// Removing either of the following two lines breaks this
I.metaClass.doIt = { -> false }
t.metaClass.doIt = { -> false }
assert !t.doIt()

Resources