Because of problems with Powermock and Java 11, we have had to use the #PowerMockIgnore on all our test classes.
#PowerMockIgnore({ "javax.management.*", "com.sun.org.apache.xerces.*", "javax.xml.*",
"org.xml.*", "org.w3c.dom.*", "com.sun.org.apache.xalan.*", "javax.activation.*" })
In order to avoid duplicating this in all test classes, we created a custom annotation to be used instead that had this PowerMockIgnore defined on one place.
So that all we would need in all our test classes would be
#SuppressPowerMockInitError
However: This custom annotation does not seem to work.
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
#Retention(RUNTIME)
#Target({ TYPE, METHOD })
#Inherited
#Documented
#PowerMockIgnore({ "javax.management.*", "com.sun.org.apache.xerces.*", "javax.xml.*",
"org.xml.*", "org.w3c.dom.*", "com.sun.org.apache.xalan.*", "javax.activation.*" })
public #interface SuppressPowerMockInitError {
}
It does not look like it is possible to achieve this with annotations.
However creating an abstract class that has this common annotation seems like the best way to achieve this.
import org.powermock.core.classloader.annotations.PowerMockIgnore;
#PowerMockIgnore({ "javax.management.*", "com.sun.org.apache.xerces.*", "javax.xml.*",
"org.xml.*", "org.w3c.dom.*", "com.sun.org.apache.xalan.*", "javax.activation.*" })
public abstract class AbstractPowerMockTest {
}
Related
I am trying to create an aspect class that with a method of type after or before, finds a target class annotation and prints a text when it is instantiated but it does not work.
Annotation
package com.example.demo
#Target(AnnotationTarget.CLASS)
#Retention(AnnotationRetention.RUNTIME)
annotation class AutoGenerateCode()
Aspect
package com.example.demo
import org.aspectj.lang.JoinPoint
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Before
import org.springframework.stereotype.Component
#Aspect
#Component
class AutoGenerateCodeAspect {
#Before("#annotation(AutoGenerateCode)")
fun before(joinPoint: JoinPoint) {
println("\n\nBEFORE\n\n")
}
}
Dto class
package com.example.demo
#AutoGenerateCode
class FakeDto {
val id = ""
}
Main
package com.example.demo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.EnableAspectJAutoProxy
#SpringBootApplication(scanBasePackages = ["com.example"])
#EnableAspectJAutoProxy
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
val fakeDto = FakeDto()
println(fakeDto)
}
This prints the object of the FakeDto class, but not the message "BEFORE"
Versions:
JAVA: 11
SpringBoot: 2.4.1
Kotlin: 1.4.21
Help, please
There are two reasons why it does not work:
FakeDto - is not managed by Spring in your case, so Spring AOP has no chance to intercept calls to FakeDto (you might need to use LTW)
#annotation pointcut designator applies to method executions where the method has the given annotation - in your case the method is toString and it obviously does not have #AutoGenerateCode annotation
here Alexander have shed some light on the problem.
(Using OpenJDK-13 and JUnit5-Jupiter)
The problem is that my unit tests each make use of a not-small JUnit annotation system, something like this:
#ParameterizedTest
#MethodSource("myorg.ccrtest.testlogic.DataProviders#standardDataProvider")
#Tags({#Tag("ccr"), #Tag("standard")})
This makes test authoring a little tedious, test code a little long and of course, when a change is needed, it's a chore!
Was wondering if I could create my own JUnit annotation: #CcrStandardTest, which would imply all of the annotations above?
I also tried shifting the annotations up in the class definition (hoping they would then apply to all methods of the class), but the compiler says no: "#ParameterizedTest is not applicable to type"
You can make a composed annotation:
JUnit Jupiter annotations can be used as meta-annotations. That means that you can define your own composed annotation that will automatically inherit the semantics of its meta-annotations.
For example:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
#Documented
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
#ParameterizedTest
#MethodSource("myorg.ccrtest.testlogic.DataProviders#standardDataProvider")
#Tag("ccr")
#Tag("standard")
public #interface CcrStandardTest {}
You would then place the composed annotation on your test method:
#CcrStandardTest
void testFoo(/* necessary parameters */) {
// perform test
}
There are some modules that contain methods which are marked with the following annotation:
#SuppressWarnings({"WeakerAccess"})
When this annotation is added,
the compiler does not give warning about the access modifier can be more private.
Some of the time this is done because some child class (outside the module) will override the method.
When this is the case,
we are required to add a comment stating that the method be overridden.
Now,
for every method and variable,
we have two things,
the annotation and the comment.
Does Java let us create an annotation which can indicate both cases.
This is what I have:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
#Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
#Retention(RetentionPolicy.SOURCE)
#SuppressWarnings({"WeakerAccess"})
public #interface WillBeOverriden { } // Ignore the ugly name
The goal of this new annotation is that it will behave exactly the same as the SuppressWarnings annotation and removes the need to add a java comment; since the annotation will act as the comment.
This stackoverflow question seems to have the answer,
but my compiler still complains that the field can be more private.
the standard use of these works great, #TmsLink("foo") #Issue("bar) However when using a dataProvider scenario, how can I programmatically set these values on each iteration of the #Test method?
Each csv entry for my test data will contain both an Id for TmsLink and Issue, how can I make each test set its own for good reporting purposes? We can do it with SeverityLevel which looks like a simple enum, however Issue/TmsLink are interfaces with #Target at Method/Type only
SeverityLevel severity = severityLevel.CRITICAL;
package io.qameta.allure;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to link tests with issues.
*/
#Documented
#Inherited
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE})
#Repeatable(Issues.class)
public #interface Issue {
String value();
}
Thank you.
to anyone coming along to this at a later stage, I figured it out by overriding the annotation values at runtime, its not amazing by any stretch but it works, I wrote up a blog post on the subject:
https://symonk.github.io/2017-10-26-overriding-allure-reporting-annotational-values-at-runtime-for-issue-tmslink-displayname/
In this code we have one user defined Annotation but without body any method what could be use of this
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.SOURCE)
#Target( { ElementType.TYPE })
public #interface InputBean {
}
The #Retention(RetentionPolicy.SOURCE) tells us that whatever use it has, it's only at the source code level -- the annotation is forgotten by the time the compiler is done, and isn't in the generated class files.
That leaves two options:
as a visual clue (ie, documentation) to human coders
to be used by an annotation processor
Without knowing more, we can't tell which of those is the case here.