Moving some common annotations from a test class to a base one just doesn't work in Quarkus, is this intended or I'm missing something?
This works:
#QuarkusTest
#TestProfile(FunctionalTestProfile.class)
class FrontendControllerTest {...}
This doesn't work:
#QuarkusTest
#TestProfile(FunctionalTestProfile.class)
public class BaseFunctionalTest {}
class FrontendControllerTest extends BaseFunctionalTest {...}
Annotations just don't get applied to child classes
The #QuarkusTest and #TestProfile annotations are not declared #Inherited, so this should not be expected to work.
Related
I am aware that I can make a TestSuite enumerating all the classes that I want, for example:
#RunWith(Suite.class)
#SuiteClasses({SQLServerTests1.class, SQLServerTest2.class, ... })
public class AllSQLServerTests {}
However I have almost 100+ classes and I don't want to have to remember to include any new one in the #SuiteClasses annotation.
As my classes have a naming convention (starting with "SQLServer" for example) I am searching for a way to do something like this:
#RunWith(Suite.class)
#SuiteClasses(prefix="SQLServer")
public class AllSQLServerTests {}
is it possible with plain JUnit? with spring or any other framework?
Tag'em
You can add many tags to each test or test class:
#Test
#Tag("red")
#Tag("production")
public void testWithColour() {...}
#RunWith(JUnitPlatform.class)
#IncludeTags("red & !production")
public class JUnit5Example {
//...
}
You can also use #ExcludeTags but it cannot co-exist with #IncludeTags
Run all in test package
#RunWith(JUnitPlatform.class)
#SelectPackages("com.acme.megaproduct.slowtests")
public class JUnit5Example {
//...
}
Write custom Test Runner
Perhaps none of the above can acommodate your needs, in which case you can add custom filtering by writing your own runner.
See here for step by step how to do it.
Then you just use it like:
#RunWith(MyCustomRunner.class)
public class CustomTestSuite {
//...
}
a question:
When I do something like:
package path.to.common.package.test;
#BeforeClass
public class CommonTestSetup {
public void setUp() {
// Setup Stiff
}
}
And the other class setup in the same package:
package path.to.common.package.test;
public class TestTest extends CommonTestSetup {
#Test
public void testGetTestReturnsCorrectStrings() {
// do asserts etc
}
}
And then executing JUnit test on testGetTestReturnsCorrectStrings I am getting an error:
org.junit.runners.model.InvalidTestClassError: Invalid test class 'org.junit.runner.manipulation.Filter':
1. No runnable methods
at org.junit.runners.ParentRunner.validate(ParentRunner.java:456)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:99)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:84)
at org.junit.runners.JUnit4.<init>(JUnit4.java:23)
at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:66)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:37)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:66)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:39)
at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:36)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createFilteredTest(JUnit4TestLoader.java:80)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:71)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:46)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:523)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)
Why is that? Does it mean JUnit 4 does not support Test classes extending a base class?
The idea behind this was to create a single SetUp base class, shared by many other test classes that need it.
Originally I even tried to have the base class in another package entirely, then moved it to the same package for testing, and got a different error (the one above).
use import org.junit.Test;
instead of import org.junit.jupiter.api.Test;
Based on the JUnit documentation:
Annotating a public static void no-arg method with #BeforeClass causes it to be run once before any of the test methods in the class
So move the #BeforeClass annotation to the setUp method and make into a static method.
You may also check for things like
class classname {
class another class{
}
}
Keep one class in file it helps
I experienced similar ... I hopes it help someone ;-)
I am new to JUnit. Following is my class hierarchy where classes at top and bottom of the hierarchy has #Test methods. When I execute whole bunch, ConverterBaseEnquiryTest which is at middle of the hierarchy is also getting executed. (That's my guess because I see exception in surefire reports with this name).
And I am getting initialization errors from ConverterBaseEnquiryTest because it wasn't supposed to be executed. Is there any way to figure out why this is happening?
Following is my hierarchy:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {
"classpath:spring/test-default-context.xml"
})
#TransactionConfiguration( transactionManager="profile.transactionManager", defaultRollback=false )
#Ignore
public class BaseCommonTest extends AbstractTransactionalJUnit4SpringContextTests {
abstract public class ConverterBaseTest<F,T> extends BaseCommonTest {
// ...
}
public class ConverterBaseEnquiryTest<F, T> extends ConverterBaseTest<Enquiry, T> {
// ...
}
public class EnquiryToDvsMedicareRequestConverterTest extends ConverterBaseEnquiryTest<Enquiry, DvsMedicareRequest> {
// ...
}
I think this is because #Ignore annotation is not inheritable, so JUnit will execute tests in subclasses. (Although posting the stacktrace would help us).
This means you will also need to place #Ignore on all subclasses.
Alternatively, to save you from that, you could perhaps use #IfProfileValue (which is inherited) on the base-class to disable the tests. This is a Spring annotation supported by the SpringJUnit4ClassRunner.
I'm studying for Java SE 7 certification exam and I'm doing some boring excercises about inheritance and access modifiers.
But now I'm getting an unexpected behavior applying inheritance. In my base package com.testpkg I have an abstract class:
package com.testpkg;
public abstract class Abstract {
public int test();
}
NOTE that I voluntarily omitted the abstract modifier for the test() method.
Then I have a concrete class extending Abstract in package com.testpkg.sub:
package com.testpkg.sub;
public class Concrete extends Abstract {
public int test() {
return 0;
}
}
I test this classes using:
package com.testpkg;
import com.testpkg.sub.Concrete;
public class TestMain {
public static void main(String[] args) {
Abstract c = new Concrete();
System.out.println(c.test());
}
}
If I try to compile this, I obviously get two errors:
The method test() requires a body instead of a semicolon
But if I run test class: 0 is printed on console!
This seems very strange to me. Can you explain why the code is working even test() is wrongly declared in Abstract class?
NOTE I'm using Eclipse IDE to compile/run my code.
You need an abstract qualifier on your test() method. You're likely running an old class file. If you change the value of your return statement to something besides 0, you will see that it isn't running this code.
Eclipse allows you to run "half baked" code. The reason why it runs fine here is because, at runtime, you never really depend on the specifics of the Abstract class so it doesn't really matter if you have this type of compile error in it.
Yours class Abstract has compilation errors, because non abstract method should be defined, so it should have a body. abstract qualifier is optional only in case of interfaces.
In my project there's a common base class that all client classes extend. This has an #Autowired field that needs to be injected by Hibernate. These are all grouped together in another class that has an #Autowired collection of the base class.
In order to reduce boilerplate for client code I'm trying to get #Component inherited. With #Component not doing this by default (apparently it used to though), I created this workaround annotation
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Component
#Inherited
public #interface InheritedComponent {
}
... and annotated the base class with it. Its not pretty but I hoped it would work. Unfortunately it didn't, which really confuses me as #Inherited should make it work
Is there any other way to get #Component inherited? Or do I just have to say that any class that extends the base class needs this boilerplate?
The problem is that the Component annotation type itself needs to be marked with #Inherited.
Your #InheritedComponent annotation type is correctly inherited by any classes that extend a superclass which is marked with #InheritedComponent - but it does not inherit #Component. This is because you have #Component on the annotation, not the parent type.
An example:
public class InheritedAnnotationTest {
#InheritedComponent
public static class BaseComponent {
}
public static class SubClass extends BaseComponent {
}
public static void main(String[] args) {
SubClass s = new SubClass();
for (Annotation a : s.getClass().getAnnotations()) {
System.out.printf("%s has annotation %s\n", s.getClass(), a);
}
}
}
Output:
class brown.annotations.InheritedAnnotationTest$SubClass has annotation #brown.annotations.InheritedComponent()
In other words, when resolving what annotations a class has, the annotations of the annotations are not resolved - they do not apply to the class, only the annotation (if that makes sense).
I've dealt with this issue by creating my own annotation (heritable) and then customizing classpath scanning:
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Component
#Inherited
public #interface BusinessService {
}
Spring configuration look likes this:
<context:component-scan base-package="io.bar">
<context:include-filter type="annotation"
expression="io.bar.core.annotations.BusinessService" />
</context:component-scan>
from Spring doc 5.10.3 Using filters to customize scanning