I´m trying to write a custom Runner which simply does the Tests in a random order. The runner:
public class TestClassRunnerForParameters extends BlockJUnit4ClassRunner {
public TestClassRunnerForParameters(Class<?> type) throws Exception {
super(type);
}
protected java.util.List<org.junit.runners.model.FrameworkMethod> computeTestMethods() {
java.util.List<org.junit.runners.model.FrameworkMethod> methods = super
.computeTestMethods();
Collections.shuffle(methods);
return methods;
}
}
Now this works fine if it is not a parameterized Test. Is it possible to do this using a Parameter Test? Implementing the Parameterized interface?
I'd say the error is pretty self-descripting:
Custom runner class TestClassRunnerForParameters should have a public constructor with signature TestClassRunnerForParameters(Class testClass)
Your class has no constructor with that signature. Its only constructor has parameters Class<?> type, List<Object[]> parameterList and int i. You should remove the latter two arguments. Plus, that constructor isn't public; you should add public in front of it.
Besides, if you're trying to build parametrised tests, you might be intested in the org.junit.runners.Parameterized runner, as it does exactly that. Here's a good tutorial.
Simply add a constructor, (as advised):
public TestClassRunnerForParameters(Class testClass) {
...
}
And have it delegate to your constructor. Your constructors should be public in this case, as JUnit/Surefire is using reflection.
Related
I have a super abstract class that has some common implemented methods and other abstract methods to be implemented by a subclass. One of the common implemented methods is a method to be annotated as #Scheduled, but I want the subclass to define how this schedule should be defined (fixed delay, fixed rate or cron .. etc). How to implement such behaviour ?
One approach I thought of is to override the method to be scheduled in the subclass such that it just call its corresponding method in the super class and add the #Scheduled on it with the desired definition, but I don't know how to enforce the subclass to do so as this method is not abstract.
Super Abstract Class
public abstract class SuperClass {
public abstract void x();
public void y() {
// Some implementation
}
// Method to be scheduled.
public void scheduledMethod() {
x();
y();
}
}
Subclass
public class Subclass extends SuperClass {
#Override
public void x() {
// Some implementation
}
// How to enforce the developer to add this ?
#Scheduled(cron = "0 0 0 * * ?")
public void scheduledMethod(){
super.scheduledMethod();
}
}
I couldn't get my head around how you could use #Scheduled but, I've an alternative:
In your abstract class, require a method to be implemented by subclasses to return the schedule:
public String getCronString();
Programmatically schedule the task using Scheduler using the method getCronString() that's implemented in your subclasses, to return the cron schedule. Few examples on how to programmatically schedule tasks with Spring boot:
https://www.baeldung.com/spring-task-scheduler
SO Question
Basically, if your subclasses are not implementing public String getCronString(); your code won't compile.
One option would be to check that the #Scheduled annotation is present (or meta-present) at bean creation time. This can be easily achieved using reflection in a #PostConstruct method on the superclass:
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;
public abstract class SuperClass {
...
#PostConstruct
public void enforceScheduling() {
boolean annotationPresent = AnnotationUtils.getAnnotation(ClassUtils.getMethod(getClass(), "scheduledMethod"), Scheduled.class) != null;
if (!annotationPresent) {
throw new IllegalStateException("#Scheduled annotation missing from scheduledMethod");
}
}
}
This will cause an exception to be thrown at application start-up time when Spring attempts to create the bean, failing fast and making it very obvious what is missing.
One thing I've done in the past in projects with constraints on a class hierarchy that I could not easily check at compile or runtime was to write a unit test that iterated through every concrete (non-abstract) instance of the class and checked whether it met that constraint.
Since this is using Spring, we probably care more that each bean of this type matches the constraint than whether each subclass on the classpath does.
The constraint in this case is that the #Scheduled annotation is present (or meta-present) on the given method in the subclass. The presence of the annotation can be easily achieved using reflection given the Class object of the subclass.
Putting this together, we can write a unit test utilizing this technique:
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;
#SpringBootTest
public class SuperClassTest {
#Autowired
private List<SuperClass> beansOfThisType;
#Test
public void allBeansMustBeScheduled() {
for (SuperClass bean : beansOfThisType) {
boolean annotationPresent = AnnotationUtils.getAnnotation(ClassUtils.getMethod(bean.getClass(), "scheduledMethod"), Scheduled.class) != null;
assertTrue(annotationPresent, "#Scheduled annotation missing from scheduledMethod for " + bean.getClass());
}
}
}
Checking every object of the type on the classpath rather than just the Spring beans would be a very similar approach; the difference would be the mechanism to get the list of Class objects to check. Getting the matching objects from the classpath is non-straightforward enough that it's outside the scope of this answer. How do you find all subclasses of a given class in Java? lists a number of ways to accomplish it.
I have a AbstractBaseRepository. All my Repositories extends from this class. I created another class RepositoryFactory to create any instance of Repository. Due to early binding of static method, I am facing problem.
public abstract class AbstractBaseRepository {
public static <T extends AbstractBaseRepository> T getNewInstance(EntityManagerFactory entityManagerFactory) {
throw new RuntimeException("Override and provide valid initialization");
}
...
}
public class RepositoryFactory {
public static <T extends AbstractBaseRepository> T getRepository(Class<T> cls) {
return T.getNewInstance(entityManagerFactory);
}
...
}
an example subclass
public class DeviceModelRepo extends AbstractBaseRepository {
public static DeviceModelRepo getNewInstance(EntityManagerFactory entityManagerFactory) {
return new DeviceModelRepo(entityManagerFactory);
}
...
}
Whenever I call getRepository() with a valid subclass of AbstractBaseRepository, runtime exception is thrown. This is due to early binding of static methods. During compile time, getNewInstance gets bound with AbstractBaseRepository rather than at runtime with actual type of the class. Any good workarounds?
My first suggestion is using Spring. It is very easy to get a list of all beans created with a certain interface.
Also, if you think of your Repository instances as a type of "plug-in" you might see how Java's ServiceLoader class can help.
Also, another approach is to use a switch statement in the factory and create the instances for each case rather than using static methods on the Repository subclasses.
Finally, I don't recommend reflection solutions but there are ways to load the class based on its name and reflectively creating a new instance.
But overriding static methods is not possible.
What I have understood by seeing your code is that you want to have different implementations of AbstractBaseRepository such as DeviceModelRepo. Then you want a factory class to create the instance of specific implementation of AbstractBaseRepository. Here the major problem is you try to overriding static methods which can never be overwritten but subclass will hide the parent implementation. Please don't use static method for overriding. You can change your implementation as given below and this issue will be resolved.
public abstract class AbstractBaseRepository {
public AbstractBaseRepository(EntityManagerFactory entityManagerFactory){
...
}
//removed method getNewInstance(EntityManagerFactory entityManagerFactory)
...
}
Then below implementation for subclass.
public class DeviceModelRepo extends AbstractBaseRepository {
public DeviceModelRepo(EntityManagerFactory entityManagerFactory) {
super(entityManagerFactory);
...
}
//removed method getNewInstance(EntityManagerFactory entityManagerFactory)
...
}
Now I am providing you two implementation of factory class.
One is having different method for each of implementation, such as getDeviceModelRepository().
Another solution is to use reflection and get repository instance by passing the implementation repository class.
public class RepositoryFactory {
//Solution-1, create separate method for each of repository like below
public static AbstractBaseRepository getDeviceModelRepository() {
return new DeviceModelRepo(entityManagerFactory);
}
//Solution-2, use reflection to get instance of specific implementation
//of AbstractBaseRepository
public static <T extends AbstractBaseRepository> T
getRepository(Class<T> repoClass) throws Exception{
return repoClass.getConstructor(EntityManagerFactory.class)
.newInstance(entityManagerFactory);
}
...
}
With reflection solution, you can get the repository instance as given below.
RepositoryFactory.getRepository(DeviceModelRepo.class)
I'm attempting to mock an abstract class, but from what I've seen, I don't think it's possible. We have some classes that use generics, that must extends a specific abstract class. There's a whole group of them and they have been mocked successfully. The abstract class has one method that deals with returning the generic and looks like this:
public abstract class ChildPresenter <T extends ChildView> {
private T view;
public abstract T getView();
}
The class we are testing has the following in it:
public class ParentPresenter {
private ConcreteChildPresenter1 childPresenter1;
private ConcreteChildPresenter2 childPresenter2;
private ConcreteChildPresenter3 childPresenter3;
private ConcreteChildPresenter4 childPresenter4;
List<ChildPresenter> childPresenters;
}
In the constructor, these classes are injected in, using Google Guice, set to the variables, and added to the list of child presenters.
The method under test is one that iterates over all of the childPresenters objects and runs the method getView().
I attempted it this way in my test class:
public class ParentPresenterTest {
private ConcreteChildPresenter1 childPresenter1;
private ConcreteChildPresenter2 childPresenter2;
private ConcreteChildPresenter3 childPresenter3;
private ConcreteChildPresenter4 childPresenter4;
private List<ChildPresenter> childPresenters;
//This is an abstract class
private ChildView childView;
#BeforeTest
public void createInjector() {
Guice.createInjector(...//Creates a fake module and does binding for the variables mentioned earlier
//e.g.
childPresenter1 = mock(ConcreteChildPresenter1.class);
binder.bind(ConcreteChildPresenter1.class).toInstance(childPresenter1);
//e.t.c for other variables
//Same for child view
childView = mock(ChildView.class);
binder.bind(ChildView.class).toInstance(childView);
}
childPresenters = new ArrayList<ChildPresenter>();
childPresenters.add(childPresenter1);
//Add all child presenters
for(ChildPresenter childPresenter : childPresenters) {
when(childPresenter.getView()).thenReturn(childView);
}
}
}
The problem happens at the line when(childPresenter.getView()).thenReturn(childView); as Mockito complains with the following message:
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
ChildView$$EnhancerByMockitoWithCGLIB$$2f6a4bd5
cannot be returned by getView() getView() should return ConcreteChildView1
*** If you're unsure why you're getting above error read on. Due to the nature of the syntax above problem might occur because:
This exception might occur in wrongly written multi-threaded tests. Please refer to Mockito FAQ on limitations of concurrency testing.
A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
Which I can understand, but it seems a waste to mock each individual concrete ChildView when all I want to do is confirm the mocked ChildView called a single method using the following:
verify(childView, atLeast(childPresenters.size())).getView();
Is there another way to do this? Can I somehow use mocked abstract classes in place of the concrete ones?
EDIT Here is a concrete version of how the getView() method is implemented:
public ConcreteChildPresenter1<ConreteChildView1> {
#Override
public ConreteChildView1 getView() {
view.buildView();
return view;
}
}
And the abstract ChildView class that all child views extend:
public abstract ChildView {
public abstract void buildView();
}
Since each child presenter returns a view of a specific type, you can't, as you already understood, substitute them with mocks of the abstract class ChildView.
There is a way to get at runtime the concrete type of ChildView only if you provide a proper implementation like explained here: Get generic type of class at runtime
Then you may initialize the presenters' mocks in this way:
for(ChildPresenter childPresenter : childPresenters) {
//this getter returns the needed runtime class
when(childPresenter.getView()).thenReturn(mock(childPresenter.getViewType()));
}
Based on the refinements, the mocked ChildView is based on the wrong superclass. I think you can fix it at Guice injector:
Guice.createInjector(...//Creates a fake module and does binding for the variables mentioned earlier
// ...
//Same for child view
childView = mock(ConcreteChildPresenter1.class); // this is the fix
binder.bind(ChildView.class).toInstance(childView);
}
Following is my class
public class SomeClass {
public ReturnType1 testThisMethod(Type1 param1, Type2 param2) {
//some code
helperMethodPublic(param1,param2);
//more code follows
}
public ReturnType2 helperMethodPublic(Type1 param1, Type2 param2) {
//some code
}
}
So in the above class while testing testThisMethod(), I want to partially mock helperMethodPublic().
As of now, I am doing the following:
SomeClass someClassMock =
PowerMock.createPartialMock(SomeClass.class,"helperMethodPublic");
PowerMock.expectPrivate(someClassMock, "helperMethodPublic, param1, param2).
andReturn(returnObject);
The compiler doesn't complain. So I try to run my test and when the code hits the helperMethodPublic() method, the control goes into the method and starts to execute each line of code in there. How do I prevent this from happening?
Another solution that doesn't rely on a mock framework would be to override 'helperMethodPublic' in an anonymous subclass defined within your test:
SomeClass sc = new SomeClass() {
#Override
public ReturnType2 helperMethodPublic(Type1 p1, Type2 p2) {
return returnObject;
}
};
Then when you use this instance in your test it will run the original version of 'testThisMethod' and the overridden version of 'helperMethodPublic'
I think it is because of what Jeff said.
Try this - setting up an expectation just as any other mocked method:
SomeClass someClassMock = PowerMock.createPartialMock(SomeClass.class,
"helperMethodPublic");
EasyMock.expect(someClassMock.helperMethodPublic(param1, param2)).
andReturn(returnObject);
PowerMock.replayAll();
I would guess this is because your "helperMethodPublic" is not a private method (as in PowerMock.expectPrivate). PowerMock is a framework that extends other mocking frameworks to add things such as mocking private and static methods (which JMock, Mockito, etc don't handle). Doing a partial mock of public methods should be something your underlying mock framework handles.
Let's say I have a test class called testFixtureA with several methods testA, testB, testC, etc, each with #Test annotation.
Let's now say I subclass testFixtureA into class called testFixtureAB and I don't overwrite anything. testFixtureAB is empty as for now.
When I run tests from testFixtureAB, methods testA, testB and testC are executed by test runner because test runner doesn't distinguish between test methods from class and baseclass.
How can I force test runner to leave out tests from baseclass?
and I don't overwrite anything.
testFixtureAB is empty as for now
There's your answer. If you want to not run testB from the main class, overrride it:
public class testFixtureAB extends testFixtureA {
#Override
public void testB() {}
}
Restructure your test classes.
If you don't want to use the tests from the baseclass, then don't extend it
If you need other functionality from the base class, split that class in two - the tests, and the other functionality
ignoring the whole base class:
#Ignore
class BaseClass {
// ...
}
check out this example
It's quite easy to achieve implementing some few classes:
Create your own TestRunner
Create an annotation like #IgnoreInheritedTests
Create a class that extends org.junit.runner.manipulation.Filter
On the filter class:
public class InheritedTestsFilter extends Filter {
#Override
public boolean shouldRun(Description description) {
Class<?> clazz = description.getTestClass();
String methodName = description.getMethodName();
if (clazz.isAnnotationPresent(IgnoreInheritedTests.class)) {
try {
return clazz.getDeclaredMethod(methodName) != null;
} catch (Exception e) {
return false;
}
}
return true;
}
#Override
public String describe() {
// TODO Auto-generated method stub
return null;
}
}
on your custom runner:
/**
* #param klass
* #throws InitializationError
* #since
*/
public CustomBaseRunner(Class<?> klass) throws InitializationError {
super(klass);
try {
this.filter(new InheritedTestsFilter());
} catch (NoTestsRemainException e) {
throw new IllegalStateException("class should contain at least one runnable test", e);
}
}
In Junit 5, you can make base class as abstract and extends it with a concrete class.
When you run the abstract in your IDE, your subclass will get executed instead.
In the latest JUnit you can use the #Rule annotation on the subclass to inspect the test name and intercept the test run to ignore the test dynamically. But I would suggest that #Bozho's idea is the better one - the fact that you need to do this indicates a bigger problem that probably shows inheritance is not the right solution here.
I know, it's not the answer...
Consider the reason why you extend concrete test classes. You do duplicate test methods that way.
If you share code between tests then consider writing base test classes with helper and fixture setup methods or test helper class.
If for running tests then try organizing tests with suites and categories.
What if you want to execute the same test for different configurations of the same test suite?
For example, let's say you have Class A with test1, test2 and test3 methods that hit an embedded database then you want to create separated "setUp" and "tearDown" for every embedded vendor (H2, HyperSQL, etc) but runs the same testing for each one.
I would like to extend a class that contain those test methods and configure it in a subclass. My problem is that the super class SHOULD NOT be considered as eligible for the test runner. The problem arises when the test runner executes the super class and given that don't found the corresponding setup and teardown methods, it crashs :(
In the base test class' #Test methods:
assumeTrue(getClass().equals(BaseClassTest.class));
It will ignore those in the subclass tests but not completely leave them out.
If for any reason you need two JUnit classes for same functionality, the best approach for me is:
put the common code in a parent class TestFixture with only constants and mocked services.
create two subclasses: TestFixtureA and TestFixtureB
This way you will not have duplicated code, nor double runs.
I ran into a similar issue where I had a generic abstract base class TestBase and 2 subclasses TestA, TestB that extended the base class. I wanted all tests from TestBase to run for TestA but to skip some for TestB. You can use the JUnit annotations Nested and Disabled to group tests in the base class into categories and then enable a full disable of that entire category of tests.
public class TestB extends TestBase {
// disable entire suite of inherited tests
// from the nested class declared on the parent
#Nested
#Disabled
public class ComponentCTests {}
}
public abstract class TestBase {
#Nested
public class ComponentCTests {
#Test
public void testSomething() {
// test something
}
}
}