I have a test which is extending to baseTest which is where I have included the parameters.
ATest.class
public class ATest extends BaseTest {
#Test
public void test() {
System.out.println(fSomething);
}
}
BaseTest.class
#RunWith(Parameterized.class)
public class BaseTest {
#Parameterized.Parameter
public Boolean fSomething;
#Parameterized.Parameters(name = "fSomething {0}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {{true}, {false}});
}
}
i am getting null value. If i set the constructor i am getting this error
org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [boolean arg0] in constructor.
Can someone help me understand what is happening?
I notice you use Jupiter from jUnit 5, but jUnit 4 API.
If you use jUnit 5, reimplement the test using #ParametrizedTest annotation instead. Start here: https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests
If you want to stick with the jUnit 4 API for this particular test, replace the import for the #Test annotation: Instead of org.junit.jupiter.api.Test (jUnit 5) use org.junit.Test (jUnit 4).
For completeness, I recommend adding a constructor for the parameters in the base test class:
public BaseTest(Boolean fSomething) {
this.fSomething = fSomething;
}
... or use Lombok annotation #AllArgsConstructor or #RequiredArgsConstructor in case you make the field final (preferred).
In the code posted , i see #Test is being used in the derived class and using #parameterized in base class, as you are using both the annotation you see these issues. check the usage of it.
Related
I have a custom annotation which I use as config to start off one time set-up for Junit.
#Target(TYPE) #Retention(RUNTIME)
public #interface MyAnnotation{
String host();
int port();
}
Test class:
#MyAnnotation(host="0.0.0.0", port=4567)
public class MyTest extends MyAbstractClass{
#Test
public void myTest(){
//do testy things
}
}
Superclass:
public class MyAbstractClass{
#BeforeAll
public static void start(){
Config cfg = readConfig();
//Use config to do one time set-up
}
private static Config readConfig(){
MyAnnotation ann = MyTest.class.getAnnotation(MyAnnotation.class);
return new Config(ann.host(), ann.port());
}
}
So currently, I hardcode the name of the test class (MyTest) in readConfig(..).
This won't work when I add a second test class.
One way to solve it is:
Add another #BeforeAll method in MyTest which will call the #BeforeAll in super-class and pass the class name as a param.
However, I am curious if I can read the name of the executing subclass in the superclass via some reflexion magic.
Any ideas are most welcome.
Thanks
The presence of the #BeforeAll annotation suggests you are using JUnit 5. In this case, you can use.
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestInfo;
public class MyAbstractClass {
#BeforeAll
public static void start(TestInfo ti) {
Config cfg=readConfig(ti.getTestClass().orElseThrow(IllegalStateException::new));
//Use config to do one time set-up
}
private static Config readConfig(Class<?> testClass) {
MyAnnotation ann = testClass.getAnnotation(MyAnnotation.class);
return new Config(ann.host(), ann.port());
}
}
See also the TestInfo API documentation.
This is not “Reflection Magic” but a feature provided by JUnit itself, but it’s also only JUnit which knows that the invocation of a static method annotated with #BeforeAll is associated with a particular test class it is going to process.
I would like to now, if it is possible to mock a class like
public class MyClass{
...
}
Our business logic create this object with new myClass() somewhere in the code and therefore I don't have access to the created object to mock those methods. Is there a way to replace the whole class or to overwrite those methods. I'm using mockito and I only found examples to do this like
#Test
public void myTest{
MyClass myClass = Mockito.mock(MyClass.class);
Mockito.when(myClass.myMethod()).thenReturn("hello World");
...
}
We can't use PowerMock because it isn't compatible with our test environment.
Any suggestions are welcome.
Sorry, i see only two hardcore solutions:
Make Powermock working by using PowerMockRule and PowerMock Rule Agent:
Getting javassist not found with PowerMock and PowerRule in Junit with Mockito
or
Use Java Reflection to set the mocked object to MyClass: Is it possible in Java to access private fields via reflection
I found a passable way to achieve my requirement.
I converted MyClass to a bean, just add annotation #Dependent.
#Dependent
public class MyClass{
public Integer someMethod(){
return 100;
}
}
I use MyClass in business logic like that
public class BusinessClass{
#Inject
MyClass myClass
public Integer doSomething(){
return myClass.someMethod();
}
}
After this change I'm able to mock the class in my test with annotation #Specializes
#Specializes
#Dependent
public class MyClassMock extends MyClass
{
#Override
public Integer someMethod(){
return 23; // return my mocked value
}
}
MyClass will be automatically replaced with MyClassMock in testenvironment.
I write unit test and want to use JUnitParamsRunner and MockitoJUnitRunner for one test class.
Unfortunately, the following does not work:
#RunWith(MockitoJUnitRunner.class)
#RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
// some tests
}
Is there a way to use both, Mockito and JUnitParams in one test class?
You cannot do this because according to spec you cannot put the same annotation twice on the same annotated element.
So, what is the solution? The solution is to put only one #RunWith() with runner you cannot stand without and replace other one with something else. In your case I guess you will remove MockitoJUnitRunner and do programatically what it does.
In fact the only thing it does it runs:
MockitoAnnotations.initMocks(test);
in the beginning of test case. So, the simplest solution is to put this code into setUp() method:
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
I am not sure, but probably you should avoid multiple call of this method using flag:
private boolean mockInitialized = false;
#Before
public void setUp() {
if (!mockInitialized) {
MockitoAnnotations.initMocks(this);
mockInitialized = true;
}
}
However better, reusable solution may be implemented with JUnt's rules.
public class MockitoRule extends TestWatcher {
private boolean mockInitialized = false;
#Override
protected void starting(Description d) {
if (!mockInitialized) {
MockitoAnnotations.initMocks(this);
mockInitialized = true;
}
}
}
Now just add the following line to your test class:
#Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
and you can run this test case with any runner you want.
As of JUnit 4.7 and Mockito 1.10.17, this functionality is built in; there is an org.mockito.junit.MockitoRule class. You can simply import it and add the line
#Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
to your test class.
This solution works for every possible runner, not just this mockito example. For example; for Spring, just change the runner classes and add necessary annotations.
#RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
#Test
public void subRunner() throws Exception {
JUnitCore.runClasses(TestMockitoJUnitRunner.class);
}
#RunWith(MockitoJUnitRunner.class)
public static class TestMockitoJUnitRunner {
}
}
DatabaseModelTest will be run by JUnit. TestMockitoJUnitRunner depends on it (by logic) and it will be run inside of the main in a #Test method, during the call JUnitCore.runClasses(TestMockitoJUnitRunner.class). This method ensures the main runner is started correctly before the static class TestMockitoJUnitRunner sub-runner runs, effectively implementing multiple nested #RunWith annotations with dependent test classes.
Also on https://bekce.github.io/junit-multiple-runwith-dependent-tests
Since the release of PowerMock 1.6, you can do it as easily as
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(JUnitParamsRunner.class)
public class DatabaseModelTest {
// some tests
}
Explained here https://blog.jayway.com/2014/11/29/using-another-junit-runner-with-powermock/
In my case I was trying to Mock some method in spring bean and
MockitoAnnotations.initMocks(test);
doesn't works. Instead you have to define that bean to constructed using mock method inside your xml file like following.
...
<bean id="classWantedToBeMocked" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.fullpath.ClassWantedToBeMocked" />
</bean>
...
and add that bean with autowired inside your test class like following.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations="file:springconfig.xml")
public class TestClass {
...
#Autowired
private ClassWantedToBeMocked classWantedToBeMocked;
...
when(classWantedToBeMocked.methodWantedToBeMocked()).thenReturn(...);
...
}
check out this link https://bekce.github.io/junit-multiple-runwith-dependent-tests/
using this approach i combined a #RunWith(Parameterized.class) - outer runner - with #RunWith(MockitoJUnitRunner.class) - inner runner. The only tweak i had to add was to make my member variables in the outer class/runner static in order to make them accessible for the inner/nested runner/class. gook luck and enjoy.
I wanted to run SWTBotJunit4ClassRunner and org.junit.runners.Parameterized at the same time, I have parametric tests and I want to screenshots when the SWT test fails (the screenshot feature is provided by the SWTBotJunit4ClassRunner). #bekce's answer is great and first wanted go that route but it was either quirky passing through the arguments. Or doing the parametrized in the subclass and loosing the information what exact tests passed/failed and have only the last screenshot (as the screenshot names get the name from the test itself). So either way it was bit messy.
In my case the SWTBotJunit4ClassRunner is simple enough, so I cloned the source-code of the class, gave it my own name ParametrizedScreenshotRunner and where original was extending the TestRunner, my class is extending the Parameterized class so in essence I can use my own runner instead of the previous two. Boiled down my own runner extends on top of Parameterized runner while implementing the screenshot feature on top of it, now my test use this "hybrid" runner and all the tests work as expected straight away (no need to change anything inside the tests).
This is how it looks like (for sake of brevity I removed all the comments from the listing):
package mySwtTests;
import org.junit.runners.Parameterized;
import org.eclipse.swtbot.swt.finder.junit.ScreenshotCaptureListener;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
public class ParametrizedScreenshotRunner extends TestRu Parameterized {
public ParametrizedScreenshotRunner(Class<?> klass) throws Throwable {
super(klass);
}
public void run(RunNotifier notifier) {
RunListener failureSpy = new ScreenshotCaptureListener();
notifier.removeListener(failureSpy); // remove existing listeners that could be added by suite or class runners
notifier.addListener(failureSpy);
try {
super.run(notifier);
} finally {
notifier.removeListener(failureSpy);
}
}
}
While there are no solution in JUnit 4 it is possible to register multiple extensions in JUnit 5:
#ExtendWith(MockitoExtension.class)
#ExtendWith(AnotherExtension.class)
public class MyTest {
// some tests
}
Note that JUnitParams framework is built into JUnit 5.
You can also try this:
#RunWith(JUnitParamsRunner.class)
public class AbstractTestClass {
// some tests
}
#RunWith(MockitoJUnitRunner.class)
public class DatabaseModelTest extends AbstractTestClass {
// some tests
}
I have following architecture of unit test:
#RunWith(Enclosed.class)
public class ProductTest {
#RunWith(MockitoJUnitRunner.class)
public static abstract class Base {...}
public static class Test1 extends Base{
#Test
public void foo(){...}
}
}
public static class Test2 extends Base{
#Test
public void bar(){...}
}
}
}
If I run unit tests I see following error message:
org.mockito.exceptions.base.MockitoException:
No tests found in Base
Haven't you forgot #Test annotation?
Mockito tries to say me that Base is test bit have noone method annoted with #Test
I have found decision - ignore base class.
Bit it looks like hack. Is there more elegant way?
Move Base outside the ProductTest class (can be in same file) and move RunWith to concrete classes.
I write unit test and want to use JUnitParamsRunner and MockitoJUnitRunner for one test class.
Unfortunately, the following does not work:
#RunWith(MockitoJUnitRunner.class)
#RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
// some tests
}
Is there a way to use both, Mockito and JUnitParams in one test class?
You cannot do this because according to spec you cannot put the same annotation twice on the same annotated element.
So, what is the solution? The solution is to put only one #RunWith() with runner you cannot stand without and replace other one with something else. In your case I guess you will remove MockitoJUnitRunner and do programatically what it does.
In fact the only thing it does it runs:
MockitoAnnotations.initMocks(test);
in the beginning of test case. So, the simplest solution is to put this code into setUp() method:
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
I am not sure, but probably you should avoid multiple call of this method using flag:
private boolean mockInitialized = false;
#Before
public void setUp() {
if (!mockInitialized) {
MockitoAnnotations.initMocks(this);
mockInitialized = true;
}
}
However better, reusable solution may be implemented with JUnt's rules.
public class MockitoRule extends TestWatcher {
private boolean mockInitialized = false;
#Override
protected void starting(Description d) {
if (!mockInitialized) {
MockitoAnnotations.initMocks(this);
mockInitialized = true;
}
}
}
Now just add the following line to your test class:
#Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
and you can run this test case with any runner you want.
As of JUnit 4.7 and Mockito 1.10.17, this functionality is built in; there is an org.mockito.junit.MockitoRule class. You can simply import it and add the line
#Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
to your test class.
This solution works for every possible runner, not just this mockito example. For example; for Spring, just change the runner classes and add necessary annotations.
#RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
#Test
public void subRunner() throws Exception {
JUnitCore.runClasses(TestMockitoJUnitRunner.class);
}
#RunWith(MockitoJUnitRunner.class)
public static class TestMockitoJUnitRunner {
}
}
DatabaseModelTest will be run by JUnit. TestMockitoJUnitRunner depends on it (by logic) and it will be run inside of the main in a #Test method, during the call JUnitCore.runClasses(TestMockitoJUnitRunner.class). This method ensures the main runner is started correctly before the static class TestMockitoJUnitRunner sub-runner runs, effectively implementing multiple nested #RunWith annotations with dependent test classes.
Also on https://bekce.github.io/junit-multiple-runwith-dependent-tests
Since the release of PowerMock 1.6, you can do it as easily as
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(JUnitParamsRunner.class)
public class DatabaseModelTest {
// some tests
}
Explained here https://blog.jayway.com/2014/11/29/using-another-junit-runner-with-powermock/
In my case I was trying to Mock some method in spring bean and
MockitoAnnotations.initMocks(test);
doesn't works. Instead you have to define that bean to constructed using mock method inside your xml file like following.
...
<bean id="classWantedToBeMocked" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.fullpath.ClassWantedToBeMocked" />
</bean>
...
and add that bean with autowired inside your test class like following.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations="file:springconfig.xml")
public class TestClass {
...
#Autowired
private ClassWantedToBeMocked classWantedToBeMocked;
...
when(classWantedToBeMocked.methodWantedToBeMocked()).thenReturn(...);
...
}
check out this link https://bekce.github.io/junit-multiple-runwith-dependent-tests/
using this approach i combined a #RunWith(Parameterized.class) - outer runner - with #RunWith(MockitoJUnitRunner.class) - inner runner. The only tweak i had to add was to make my member variables in the outer class/runner static in order to make them accessible for the inner/nested runner/class. gook luck and enjoy.
I wanted to run SWTBotJunit4ClassRunner and org.junit.runners.Parameterized at the same time, I have parametric tests and I want to screenshots when the SWT test fails (the screenshot feature is provided by the SWTBotJunit4ClassRunner). #bekce's answer is great and first wanted go that route but it was either quirky passing through the arguments. Or doing the parametrized in the subclass and loosing the information what exact tests passed/failed and have only the last screenshot (as the screenshot names get the name from the test itself). So either way it was bit messy.
In my case the SWTBotJunit4ClassRunner is simple enough, so I cloned the source-code of the class, gave it my own name ParametrizedScreenshotRunner and where original was extending the TestRunner, my class is extending the Parameterized class so in essence I can use my own runner instead of the previous two. Boiled down my own runner extends on top of Parameterized runner while implementing the screenshot feature on top of it, now my test use this "hybrid" runner and all the tests work as expected straight away (no need to change anything inside the tests).
This is how it looks like (for sake of brevity I removed all the comments from the listing):
package mySwtTests;
import org.junit.runners.Parameterized;
import org.eclipse.swtbot.swt.finder.junit.ScreenshotCaptureListener;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
public class ParametrizedScreenshotRunner extends TestRu Parameterized {
public ParametrizedScreenshotRunner(Class<?> klass) throws Throwable {
super(klass);
}
public void run(RunNotifier notifier) {
RunListener failureSpy = new ScreenshotCaptureListener();
notifier.removeListener(failureSpy); // remove existing listeners that could be added by suite or class runners
notifier.addListener(failureSpy);
try {
super.run(notifier);
} finally {
notifier.removeListener(failureSpy);
}
}
}
While there are no solution in JUnit 4 it is possible to register multiple extensions in JUnit 5:
#ExtendWith(MockitoExtension.class)
#ExtendWith(AnotherExtension.class)
public class MyTest {
// some tests
}
Note that JUnitParams framework is built into JUnit 5.
You can also try this:
#RunWith(JUnitParamsRunner.class)
public class AbstractTestClass {
// some tests
}
#RunWith(MockitoJUnitRunner.class)
public class DatabaseModelTest extends AbstractTestClass {
// some tests
}