I am used to JUnit running #Before methods in a superclass before #Before methods in a subclass. However, I've got a Groovy test class which inherits from another Groovy class, and they both contain #Before methods; the problem I have is that #Before method in the test class is running before the one in its superclass, and I'm getting NPEs from uninitialised variables (the superclass is supposed to take care of that).
The superclass is something like this:
import groovyx.net.http.RESTClient
import org.junit.Before
abstract class BaseTestClass {
def client
#Before
void setUp() {
client = new RESTClient()
}
}
And the subclass is something like this:
import org.junit.Before
class TestClass extends BaseTestClass {
#Before
void setUp() {
client.post(path: '/entity', body: '{"id":"test"}')
}
...
}
This is a simplified version, but I get the error: java.lang.NullPointerException: Cannot invoke method post() on null object in the setUp() method of the subclass. Any ideas what could cause this behaviour? All the docs say it should be the other way round, and I've never previously experienced any different.
I'm running using the maven-failsafe-plugin, junit-4.10 and jdk-1.6.0_31. Interestingly, I have other Groovy test classes in the same place (same package, same project, same directory) which do not suffer from this problem - the ordering of #Before methods is correct; furthermore, it appears to be deterministic - it's always the same test class that has the problem.
Thanks!
You named both of your #Before methods setUp(). The child's setUp() method overrides the parent's one. So the line client = new RESTClient() is never called.
Just pick another name.
Related
Trying to mock SQLQueryFactory of Querydsl for DAO unit testing. Using Mockito's deep stub for the very first time.
Below is the minimal code which fails
#Test
void tryMockQueryDsl() {
SQLQueryFactory sql = Mockito.mock(SQLQueryFactory.class, Mockito.RETURNS_DEEP_STUBS);
Mockito.when(sql.select(ArgumentMatchers.<Expression<?>>any())
.from(ArgumentMatchers.<Expression<?>>any())
.fetchFirst()
).thenReturn(null);
}
with the following exception:
java.lang.ClassCastException: class com.querydsl.sql.ProjectableSQLQuery$MockitoMock$1584151766 cannot be cast to class com.querydsl.sql.SQLQuery (com.querydsl.sql.ProjectableSQLQuery$MockitoMock$1584151766 and com.querydsl.sql.SQLQuery are in unnamed module of loader 'app')
What can be the problem?
Mocks can not be cast. Instead of RETURN_DEEP_STUBS mock each method on its own and return a mocked instance of the expected class.
If you do not want to suppress the warnings you will get for not defining the generic types, you can use the #Mock annotation instead to create the mocks, like described here.
This example doesn't make much sense for a testcase (as it tests nothing), but its a showcase on how to avoid the exception.
#RunWith(MockitoJUnitRunner.class)
public class Test {
#Test
public void tryMockQueryDsl() {
ProjectableSQLQuery projectableQuery = Mockito.mock(ProjectableSQLQuery.class);
// not really needed as this is the default behaviour
Mockito.when(projectableQuery.fetchFirst()).thenReturn(null);
SQLQuery query = Mockito.mock(SQLQuery.class);
Mockito.when(query.from(ArgumentMatchers.<Expression<?>>any())).thenReturn(projectableQuery);
SQLQueryFactory sql = Mockito.mock(SQLQueryFactory.class);
Mockito.when(sql.select(ArgumentMatchers.<Expression<?>>any())).thenReturn(query);
Expression expr = Mockito.mock(Expression.class);
sql.select(expr).from(expr).fetchFirst();
}
}
I need to define a custom annotations in cucumber runner class. I have a event handler class where i get a callback when a test case is finished/started etc.
The issue i am facing is i am not able to get the runner class inside the event handler class, and hence i am unable to read the custom annotations applied in the runner class.
Is there a way for that in cucumber.
Eg. in junit , i can get the custom annotation applied in the test class as :
public void testFinished(Description description) { description.getTestClass();} from where i could read my annotation.
in testng, itestContext.getTestClass().getRealClass();.
Any help would be highly appreciated.
Many thanks in advance.
Eg. i need to read the annotations here,
private EventHandler<TestCaseFinished> caseFinishedEventHandler = new EventHandler<TestCaseFinished>() {
#Override
public void receive(TestCaseFinished event) {
//Read annotations here...
}
}; /*Or here*/ private EventHandler<TestRunFinished> runFinishedEventHandler = new EventHandler<TestRunFinished>() {
#Override
public void receive(TestRunFinished event) {
}
};
Solved this issue by :
For Junit : Extending Cucumber runner class. class argument of the constructor returns the runner class where custom annotations are present.
For TestNG : Extending AbstractTestNGCucumberTests in case of TestNG. this.getClass() returns the runner class where custom annotations are present.
I am working on an API for work, we use a shared library for multiple projects for the purposing of our logging framework. The class used uses all static methods for its calls.
I am trying to Unit test an API call, I can not have it call anything on the Logging class, else it will fail.
I have tried using Powermock, but it fails on
PowerMockito.mockStatic(LoggingFramework.class);
Mockito.when(LoggingFramework.startACall(anyString())).thenReturn("someTimestamp");
returning a
ClassCastException: org.apache.logging.slf4j.SLF4JLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext
the line in LoggingFramework that throws it, is inside a static initializer block outside of any methods in the class.
In order to suppress static initialization you should use #SuppressStaticInitializationFor. So your code will look like this:
#RunWith(PowerMockRunner.class)
#SuppressStaticInitializationFor("so.LoggingFramework") //here goes fully-qualified name of a class
public class LoggingFrameworkTest {
#Test
public void test() {
//given:
PowerMockito.mockStatic(LoggingFramework.class);
Mockito.when(LoggingFramework.foo(anyString())).thenReturn("stub");
//when:
String foo = LoggingFramework.foo("ignored");
//then:
PowerMockito.verifyStatic(LoggingFramework.class, Mockito.times(1));
LoggingFramework.foo(anyString()); //two-step verification of a static method
assertThat(foo, equalTo("stub"));
}
}
Verification of a static method is performed in two steps. It is explained here
I have something like the following:
public class Foo {
public static String getValue(String key) {
return key + "_" + System.currentTimeMillis();
}
}
Now I need to have a test case for it and here is how I attempted:
#Test
public void testFoo() {
PowerMockito.mockStatic(Foo.class);
PowerMockito.when(Foo.getValue("123")).thenReturn("abcd");
PowerMockito.verifyStatic();
}
When I run the test case, I get this:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
at org.powermock.api.mockito.PowerMockito.when(PowerMockito.java:495)
Am I doing anything wrong?
Please advise.
Can you confirm that you've added a #PrepareForTest(Foo.class) annotation onto your test class as listed on the PowerMock site, and that you're using the PowerMockRunner JUnit4 runner?
Static methods are invoked with static dispatch, not dynamic dispatch using Java's normal polymorphism and method overrides. To replace the implementation, PowerMock needs to load a replacement class before the test starts running, and the runner and annotation make that happen.
Suppose I have the following interface:
public interface ISomething {
default int doStuff() {
return 2 * getValue();
}
int getValue();
}
When I now mock this interface like this:
#Mock
private ISomething _something;
#Before
public void setup() {
doCallRealMethod().when(_something).doStuff();
}
and try to test the doStuff() method like the following:
#Test
public void testDoStuff() {
when(_something.getValue()).thenReturn(42);
assertThat("doStuff() returns 84", _something.doStuff(), is(84));
}
I expect the test to succeed, but I get:
org.mockito.exceptions.base.MockitoException:
Cannot call real method on java interface. Interface does not have any implementation!
Calling real methods is only possible when mocking concrete classes.
I tried subclassing ISomething with an abstract class like this:
public abstract class Something implements ISomething {
}
and mock this class like above. With this approach, I get the same.
Does Mockito not support calling default implementations?
That's correct. The current version of Mockito doesn't support this. You could raise a feature request here. Do note that it seems to be related to issue 456 which was fixed in release 1.10.0, so please make sure you test this in the latest version first.
I was working on a project using Mockito 1.9.5 and ran into the same issue that you found. We couldn't upgrade Mockito because of the way our build server worked. The problem we ran into was when we were writing unit tests for the concrete subclasses, as we couldn't stub out or include the default methods from the interface in our mock objects (so slightly different from your example).
Here is an example subclass using your model:
public class ConcreteSomething implements ISomething {
#Override
int getValue()
{
return 42;
}
}
Then in the unit test class, we explicitly made a private inner class. This class overrode all the default methods of the concrete class under test (i.e. ConcreteSomething) with the interface's default implementation. So in this example, something like:
private class ConcreteSomethingDefaultImpl extends ConcreteSomething {
#Override
int doStuff() {
return super.doStuff();
}
}
For us, a mock made using mock(ConcreteSomething.class) couldn't have it's default methods called using doCallRealMethod(), but mock(ConcreteSomethingDefaultImpl.class) could, and more importantly, it was the default implementation code in the interface that was being used.
I hope that helps anyone else who is constrained to use a particular version of Mockito.