Practical use of metaprogramming - metaprogramming

I started to learn metaprogramming. So far I used it to read annotations in Java and create sql statements based on given class but I don't see any practical use in it. Can you give me an example where and how you used it in your programs?

Annotating a method to be recogonized as a unit test.
import static org.junit.jupiter.api.Assertions.assertEquals;
import example.util.Calculator;
import org.junit.jupiter.api.Test;
class MyFirstJUnitJupiterTests {
private final Calculator calculator = new Calculator();
#Test
void addition() {
assertEquals(2, calculator.add(1, 1));
}
}
Note that the annotation here #Test exists as a flag. When the test runner launches, it registers a listener for annotated methods, and if it encounters an annotated method that is annotated with the Test annotation interface, it will register that test in the "list of tests to run"
See https://junit.org/junit5/docs/current/user-guide/ for more details.
There are many examples of annotations in the wild. This is just but one of them.

Related

Spock- Capture method arguments in private method call of class under test

I am trying to test my Service class below
#Service
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
public class TaskTemplateService {
#NonNull
TaskTemplateRepository taskTemplateRepository;
public void doStuff() {
List<MyObject> list;
doOtherStuff(list)
}
private void doOtherStuff(List <MyObject>) {
//do stuff
}
}
When I am testing the real TaskTemplate, how can I capture what is passed to doOtherStuff?
You cannot and why would you?
Good testing means to specify the behaviour of a unit's public interface. Private methods ought to be covered via testing this way indirectly. If this is not possible then either you have dead, unreachable code or a design problem and should refactor.
BTW, the technical reason that you cannot mock/stub private methods is that most mocking tools, also the built-in feature of Spock, use dynamic proxies (DP) in order to implement mocking. DP technically are subclasses, but private methods can never be extended or even seen by subclasses or being called by them or from other classes, hence the term "private". Consequently, a mock subclass cannot check interactions with private methods.
How exactly you ought to redesign your class in order to make it testable really depends on why you want to "capture" the method argument, as you say. Do you need to replace it by a mock? Do you need to modify or verify the content of the original object?
If the object has a central meaning and you need to replace or verify it, why not make it injectable instead of creating it as a local variable, hermetically sealing it off from the outside world and making it untestable?
Or maybe in your case you could make the private method protected or package-scoped in order to make it testable. Then at least a mock could be created for it and you could capture the argument or stub the result.
I am mostly speculating here because the answer really depends on what is behind //do stuff, i.e. the very information you are hiding in your sample code.

Groovy star import and usage of "partial" packages

To my surprise I have learned today that the following works just fine in Groovy:
import java.util.concurrent.*
def atomicBool = new atomic.AtomicBoolean(true)
i.e. after the star import, I can use a 'partial' package to refer to java.util.concurrent.atomic.AtomicBoolean.
Obviously, the same is not valid in Java:
import java.util.concurrent.*;
public class Sample {
public static void main(String[] args) {
// compiler error: 'atomic' cannot be resolved to a type
new atomic.AtomicBoolean(true);
}
}
So it seems that Groovy's idea of a package is similar to C++ (or C#) namespaces in this regard.
Question to the Groovy experts:
Is this by design or is it a (potentially unintended) side effect of the way the interpreter treats star imports?
If it is by design, can you point me to a section in the documentation or language specification where this behavior is documented? (There is no mention of this in the documentation on Star Import and neither in the language spec as far as I can tell or at least I couldn't find anything.)
Based on Groovy source code, this behavior seems to be intended. Before we dig deeper into Groovy internals you have to be aware of one thing - Groovy compiles to a bytecode that can be represented by a valid Java code. It means that Groovy code like the one form your example actually compiles to something like this (without compile static and type checked transformations):
import groovy.lang.Binding;
import groovy.lang.Script;
import java.util.concurrent.atomic.AtomicBoolean;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class test extends Script {
public test() {
CallSite[] var1 = $getCallSiteArray();
}
public test(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
}
public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(InvokerHelper.class, test.class, args);
}
public Object run() {
CallSite[] var1 = $getCallSiteArray();
AtomicBoolean atomicBool = (AtomicBoolean)ScriptBytecodeAdapter.castToType(var1[1].callConstructor(AtomicBoolean.class, true), AtomicBoolean.class);
return var1[2].callCurrent(this, atomicBool);
}
}
As you can see this Java class uses full java.util.concurrent.atomic.AtomicBoolean import and this is actually what Groovy transforms your input source code to.
How does it happen?
As you may know Groovy builds Abstract Syntax Tree (AST) from the input source file and it iterates over all nodes (like expressions, variable definitions, method calls etc.) and applies transformations. Groovy uses class called ResolverVisitor that is designed to resolve types. When Groovy compiles your code it finds ConstructorCallExpression:
new atomic.AtomicBoolean(true)
It sees that the expected type of the object you are trying to create is atomic.AtomicBoolean, so ResolverVisitor starts resolving the type by calling resolveOrFail(type, cce); at line 1131.
It tries several resolving strategies that fail until it reaches method resolveFromModule at line 695. What happens here is it iterates over all star imports (single java.util.concurrent.* in your case), then it concatenates star import with the type name and it checks if qualified name created from this concatenation is a valid type class. Luckily it is in your case:
When type gets resolved, Groovy replaces initial type with this resolved valid type name in the abstract syntax tree. After this operation your input code looks more like this:
import java.util.concurrent.*
java.util.concurrent.atomic.AtomicBoolean atomicBool = new java.util.concurrent.atomic.AtomicBoolean(true)
This is what compiler gets eventually. Of course fully qualified name gets replaced with the import (this is what Java compiler does with qualified names).
Was this "feature" introduced by designed?
I can't tell you that. However we can read from the source code, that this happens on purpose and type resolving like this is implemented with intention.
Why it is not documented?
I guess no one actually recommend using imports that way. Groovy is very powerful and you are able to do many things in a many different ways, but it doesn't mean you should do so. Star imports are pretty controversial, because using star imports over explicit imports makes your code more error-prone due to possible class import conflicts. But if you want to know exact answer to this kind of questions you would have to ask Groovy language designers and core developers - they may give you straight answer without any doubts.

How to tell Spock which class to run in specific order

Im using Spock for my tests and I have multiple classes to test. I want to tell Spock to test each class in specific order. Is there a way to do this? I noticed TestNG has got #AfterTest annotation, so does Spock have something similar?
You can't specify Spock test classes execution order. However Spock allows you to specify methods execution order when you add #Stepwise annotation to your test class - in this case Spock will execute all methods in order from top to bottom and if one method fails it will ignore remaining methods in this test class.
Indicates that a spec's feature methods should be run sequentially in their declared order (even in the presence of a parallel spec runner), always starting from the first method. If a method fails, the remaining methods will be skipped. Feature methods declared in super- and subspecs are not affected.
#Stepwise is useful for specs with (logical) dependencies between methods. In particular, it helps to avoid consecutive errors after a method has failed, which makes it easier to understand what really went wrong.
Reference: http://spockframework.org/spock/javadoc/1.1/spock/lang/Stepwise.html
#Stepwise
class StepwiseExample extends Specification {
def "first test method to run"() {
// ....
}
def "second test method to run"() {
// ....
}
def "if previous method failed this one will be ignored"() {
// ....
}
}
Using org.junit.runners.Suite
Jeff Scott Brown gave a good comment about JUnit's #Suite.SuiteClasses. In this case you create a class where you can aggregate your test classes (specifications) into a single test suite and those classes will be executed in the order they have been defined in the suite. Consider following example:
import org.junit.runner.RunWith
import org.junit.runners.Suite
#RunWith(Suite)
#Suite.SuiteClasses([
Test2Specification,
Test1Specification
])
class TestSuiteSpecification { }
This suite executes two specifications Test2Specification and Test1Specification in the defined order:

Partial Mocking Class with Multiple Static Methods with GMock

I'm using GMock to add some unit testing to our existing Java projects. We have multiple places where the methods needing to be tested are static methods, which utilize additional static methods within the method we want to test.
I would like to be able to partially mock the class, pretty much all static methods on the class other than the initial entry point for testing.
For example:
class StaticClass {
static void method(String one) {
method2()
}
static void method(String one, String two) {
...
}
}
My hope is that I can mock the second static method but as soon as I do, method(String) goes MIA and executing the test fails with an expectation exception. Is there a way I can partially mock the class, maintaining the functionality of the first method but mock the static access of the second method?
I've also tried using metaClass programming to mock the method, but if I set method equal to a closure, the first method goes MIA again. Not sure how to do this with overloaded methods. Any ideas?
In Gmock, it mocks static methods and matches expectations according to their names. It means you cannot mock one overloaded method but not another.
It is the same with MOP of Groovy.
While this doesn't involve GMock specifically, you could extend StaticClass inside your test file and override the methods there

Is there any way to use groovy and java code for the same class?

I mainly program in groovy, but occasionally it's too slow. So I write a separate .java class, and put the code that needs to run faster in a java method and call that java method from my groovy code.
This causes me to end up with two separate files and two separate classes. Is there any way I could embed a java method right into the groovy file, maybe marking it with an annotation to indicate that it is java?
This is the idea behind groovy++. Marking a class or method with the #Typed annotation will cause it to use static typing instead of dynamic typing, while still retaining a lot of goodness of groovy.
While not exactly java, typed groovy++ methods generally perform about the same as java would.
More information on groovy++ is available at: https://code.google.com/p/groovypptest/wiki/Welcome
You don't need to do anything special.
Just write the Java class behind the groovy class. 99% of all Java source is valid groovy source as well.
class GroovyClass {
def a;
def doSomething(x,y) { return x*y; }
}
class JavaClass {
SomeType someVar;
public JavaClass() { /* ... */ } // some contructor
public void doit(String a, int b) {} // full typed method, that is java
}
Groovy++ is somethign completely different.
The JavaClass needs to have everything fully typed to be "Java" however your problem can be solved far easyer if you just use types in the relevant groovy methods.
class AnotherGroovyClass {
// typed
public Result someMethod(SomeArg arg1, SomeOtherArg arg2) {
}
def someVariable; // untyped
}
If you think the lack of speed comes from the dynamic nature of groovy then just use full types at the relevant points.

Resources