junit 5 custom parametrized tests - java

I'm using Junit 5 parametrized tests with custom name as follow
#ParameterizedTest(name = PARAMETERIZED_TESTS_NAME_PLACEHOLDER)
where PARAMETERIZED_TESTS_NAME_PLACEHOLDER is defined in its own utility class
public static final String PARAMETERIZED_TESTS_NAME_PLACEHOLDER = "#{index} [{argumentsWithNames}]";
the problem I'm facing is that as I'm using extensively the parametrized tests, my code is cluttered by these #ParameterizedTest(name = PARAMETERIZED_TESTS_NAME_PLACEHOLDER).
so I created a custom annotation to fix this
import java.lang.annotation.*;
import org.junit.jupiter.params.*;
#ParameterizedTest(name = PARAMETERIZED_TESTS_NAME_PLACEHOLDER)
#Inherited
public #interface CustomParametrizedTest {
}
but this annotation is ignored when I use it in the test cases
any help would be appreciated

The #ParamterizedTest annotation appears to have a retention policy of runtime suggesting it's needed and processed at runtime. Try this config
#ParameterizedTest(name = PARAMETERIZED_TESTS_NAME_PLACEHOLDER)
#Retention(RetentionPolicy.RUNTIME)
#Inherited
public #interface CustomParametrizedTest {
}
It seems odd to me that this is not the default retention policy for custom annotations, see more from this post.

Related

Java annotations logic implementation

I'm creating a java library that can be imported in multiple projects and creates a graphQL schema file with classes and queries annotated with my custom annotations.
I want that when I compile the project, the classes marked by the annotation will be added (with all their fields) into a file that will be the "schema.graphqls" file.
My question is: where I have to insert my logic implementation? Creating a method into the annotation class?
I created two custom annotations, as in the following files:
package annotations;
import java.lang.annotation.*;
#Documented
#Retention(RetentionPolicy.SOURCE)
#Target(ElementType.TYPE) //with TYPE, you can annotate class, interfaces, annotation, types or enum
public #interface GraphQLQuery {
}
GraphQLQuery.java
package annotations;
import java.lang.annotation.*;
#Documented
#Retention(RetentionPolicy.SOURCE)
#Target(ElementType.TYPE) //with TYPE, you can annotate class, interfaces, annotation, types or enum
public #interface GraphQLModel {
}
GraphQLModel.java

IntelliJ run context for JUnit TestTemplates

In JUnit 5 you can define your own test template and bind it to an annotation.
Instead of #Test or #ParameterizedTest now I can use my own test annotaion #MyTest(...)
The problem is that Intellij does not recognize this annotation as JUnit test annotation thus does not give me the option to run/debug this test.
Can I extend this list of annotations that tells IntelliJ this is a test?
Picture on the left is a standard test where the context shows a run function.
Picture on the right shows my template which works perfectly just the context does not recognize it as a test.
My test template looks like this:
#Target(
AnnotationTarget.ANNOTATION_CLASS,
AnnotationTarget.FUNCTION
)
#Retention(AnnotationRetention.RUNTIME)
#Execution(ExecutionMode.CONCURRENT)
#TestTemplate
#ExtendWith(ScTestExtension::class)
annotation class ScTest(
// ... some properties
)
class ScTestExtension : TestTemplateInvocationContextProvider {
override fun supportsTestTemplate(context: ExtensionContext): Boolean {
return true
}
override fun provideTestTemplateInvocationContexts(extensionContext: ExtensionContext): Stream<TestTemplateInvocationContext> {
// ... return invocation context
}
}
Your ScTest.java should look similar to this one:
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.Test;
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#Test
public #interface ScTest {}
Derived from https://junit.org/junit5/docs/current/user-guide/#writing-tests-meta-annotations
IIRC, IDEA and other IDEs look for an instance of Testable to display the "Run..." icon. But normally, you shouldn't use that annotation directly. It should suffice to have it meta-annotated with #Test, #TestTemplate, or friends.
Here's another example using #TestTemplate that worked (at least, two years ago): CartesianProductTest.java
#TestTemplate
#ExtendWith(CartesianProductProvider.class)
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface CartesianProductTest {...}
Here is how "IntelliJ IDEA 2019.3 EAP (Community Edition) Build #IC-193.4386.10, built on October 9, 2019" shows the usage of the #CartesianProductTest annotation today:
Perhaps you need to switch to dark mode...

Expressing Java Annotation Class with Members in Kotlin

I'm new to Kotlin and currently using v1.3.31 in an OSGI bundle development POC. I'm currently using annotation processors to generate the OSGI manifest declarations and I am trying to find the Kotlin equivalent of the following:
#ObjectClassDefinition(name="Config", description = "Sample Config")
public static #interface Config {
#AttributeDefinition(name = "A parameter", description = "Configurable param")
String myParameter() default "";
}
Given that these OSGI annotations are created as:
#Retention(RetentionPolicy.CLASS)
#Target(ElementType.TYPE)
public #interface ObjectClassDefinition
/*....*/
#Retention(RetentionPolicy.CLASS)
#Target(ElementType.METHOD)
public #interface AttributeDefinition
The closest I can get in Kotlin is using the #ObjectClassDefinition annotation on a public annotation class but since Kotlin annotation classes do not support members, I cannot use the #AttributeDefinition on a class member.
I've tried to only use a Kotlin class or interface but the annotation processor will not allow any non-annotation class.
I've also tried to create a java.lang.Annotation in Kotlin to bypass this behavior, but the compiler will not allow it.
Current partially working implementation and here's is the latest working GitHub source.:
#ObjectClassDefinition(name = "Sample Kotlin servlet",
description = "Simple Kotlin servlet with configurable properties")
public annotation class Config (
val value : String = "hello"
)
I've noticed that annotations can be particularly tricky in Kotlin. Any insight is greatly appreciated!
#ObjectClassDefinition(
name = "Sample Kotlin servlet",
description = "Simple Kotlin servlet with configurable properties")
annotation class Config (
#get:AttributeDefinition(name = "A parameter", description = "Configurable param")
val value : String = "hello")
("public" does not seem to have any effect).
See this documentation for details annotation-use-site-targets

Create Custom Dagger 2 Scope with Kotlin

I'm trying to convert a Java code into Kotlin for custom dagger scope creation.
Here is Java code:
#Documented
#Scope
#Retention(RetentionPolicy.RUNTIME)
public #interface CustomScope {
}
Once converted into kotlin here is the result
#Scope
#Documented
#Retention(RetentionPolicy.RUNTIME) annotation class CustomScope
I have a type mismatch with #Retention(RetentionPolicy.RUNTIME).I have the following error message :Required Type is AnnotationRetention but RetentionPolicy type was found.
Also #interface seems to have been replaced.
The Retention annotation class which you might have used is from the Kotlin's library (from the package kotlin.annotation).
It expects a property of the enum type AnnotationRetention. So, you can do something like this:
#MustBeDocumented
#Scope
#Retention(AnnotationRetention.RUNTIME)
annotation class CustomScope
Btw, if you look at the Annotations.kt file, you will see that that the Retention annotation will take the default property AnnotationRetention.RUNTIME when you don't pass anything to it.
So, just #Retention annotation will do too.

How annotation internally works in java

I know how to create custom annotation. But i am unable to understand how does it work internally. If i take example of spring annontation.
#PropertySource(value = { "classpath:database.properties" }).
if we see internal details of #PropertySource annotation
#Target({ java.lang.annotation.ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Repeatable(PropertySources.class)
public #interface PropertySource {
public abstract String name();
public abstract String[] value();
public abstract boolean ignoreResourceNotFound();
}
We do not have provided any implementation here for loading property file.
Then How is it loading property file from classpath. Who is working behind the scene ?
Really simple: framework. That is. All 'custom' annotations processed by frameworks using reflection. Only small scope of annotations are processed by compiler, such as #Override, #SuppressWarnings, #Retention and so on

Categories

Resources