No matter what I've tried, test end up on NullPointerException on stubbing statement.
Method to test:
public boolean selectEntity(final List<T> entities) {
if (entities.contains(helper.getLastEntity())) {
return true;
}
}
Above snippet is enough, cause (in unit test) cannot even enter into conditional statement. To clarify: getLastEntity returns field
private T lastEntity
for object of class Helper. T is an interface.
My best try is:
private #Mock Helper helper;
private #Mock List<T> entities;
...
#Test
public void testSelectEntity(){
when(entities.contains(notNull(T.class))).thenReturn(true);
when(helper.getLastEntity()).thenReturn((T) anyObject());
}
How to proceed here?
UPDATE: follow your suggestions, I rewrote test (mocks are for sure initialized this time:))
final DummyT dummyT = new DummyT();
when(helper.getLastEntity()).thenReturn(dummyT);
when(entities.contains(dummyT).thenReturn(true);
assertTrue(objectUnderTest.selectEntity(entities));
where DummyT implements T. Got null pointer on method execution, pointing on if statement.
At least two problems:
You cannot return an instance of the matcher anyObject(). Instantiate an object to return instead.
Depending on your mocking framework, you'll need to initialise mocking first. For example, in Mockito, use: MockitoAnnotations.initMocks(this);
Related
I have to deal with a legacy application that has no tests. So before I begin refactoring I want to make sure everything works as it is.
Now imagine the following situation:
public SomeObject doSomething(final OtherObject x, final String something) {
if(x != null) {
final String = someOtherMethod(x, something);
}
}
protected String someOtherMethod(final OtherObject x, final String something) {
....
}
Now I want to make sure that protected method is called as well
So I did this
#InjectMocks // Yes there is more going on here
private MyTestObject myTestObject;
private MyTestObject spy;
private static final OtherObject VALID_OTHER_OBJECT = new OtherObject();
#Before
public void setup() {
this.spy = Mockito.spy(myTestObject);
}
#Test
public void ifOtherObjectIsNotNullExpectSubMethodToBeCalled() {
myTestObject.doSomething(VALID_OTHER_OBJECT, null);
verify(spy).someOtherMethod(VALID_OTHER_OBJECT, null);
}
I get a failing test and "Wanted but not invoked..." for someOtherMethod().
I jumped right into debug mode and checked. That method is called!
What could be the cause of this? Am I misusing the spy here?
Edit: I want to stretch that I know this is not what you typically test for, especially since someOtherMethod(...) has a non-void return-value here. But imagine the return value was void...
Basically I just want to understand why the spy fails here.
As per its Javadoc, Mockito.spy(object) creates a copy of the passed in object. Calling methods on the original passed in object then does not register on the spy, because the spy instance is not the same object.
Change myTestObject.doSomething(...) to spy.doSomething(...) and it should work.
Alternative (different way to achieve the same thing):
Consider using the #Spy annotation on your myTestObject.
Be sure to add MockitoAnnotations.initMocks(this); to your initialization method (in your junit test).
The #Before and #Mock annotations are useful as well.
I had one object creating another and that other object making calls. So I needed to make that internal object be using the spied reference instead. I used reflection and updated the reference using Whitebox.
TestAddressFragment fragment = spy(new TestAddressFragment());
AddressPresenter presenter = fragment.getPresenter();
Whitebox.setInternalState(presenter, "view", fragment );
Now my fragment could check if its method was called.
verify( fragment ).showAddress(any(), anyBoolean());
I have a method in my MainActivity (Android) and I want to mock the A instance :
public void some_method() {
A a = new A();
....
}
so I created a kind of factory class as such
public class SomeFactory(){
// some constructor
public A populateWithParameter(Parameter parameter){
return new A(parameter)
}
}
and the method above turns into
public void some_method(SomeFactory someFactory) {
A a = someFactory.populateWithParameter(parameter);
a.method_call()
....
}
I tried this
#Mock
SomeFactory someFactory;
public void testSomeMethod() throws Exception {
SomeFactory someFactory = new SomeFactory();
when(someFactory.populateWithParameter(
some_parameter)).thenReturn(null);
mainActivity.some_method(someFactory);
...
}
but I get this error message
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);
You are not mocking your factory. Also, wrong method call.
Do this instead.
SomeFactory someFactory = mock(SomeFactory.class)
when(someFactory.populateWithParameter(
some_parameter)).thenReturn(null);
mainActivity.some_method(someFactory);
UPDATE
Your code has changed so for completeness this is what your test should look like. In the updated code above, you were overwriting your mock with a real object. Assuming your objects are correctly set up. Notice the different syntax for providing a return object. I think this is more readable.
#Mock SomeFactory mockFactory;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this); // set up annotated mocks
}
#Test
public void testSomeMethod() {
A subject = new A();
doReturn(subject).when(mockFactory)
.populateWithParameter(any(Parameter.class));
main_activity.some_method(mockFactory);
verify(mockFactory,times(1)).populateWithParameter(any(Parameter.class));
}
Best Practices
When naming methods and variables, use camelCase. So main_activity becomes MainActivity, some_method becomes SomeMethod.
You need a way to overwrite the instance of A from your test. Typically this is done using an injection framework. For a simple case, you can make the field under test protected (assuming the test class is in the same package as the class under test).
The error you are seeing comes interacting with a "real" object as if it was a mock.
In this case SomeFactory is a real object so it cannot be when()ed
From the point of view of response of #DiscoS2, there is indeed an issue with this declaration
MockitoAnnotations.initMocks(this);
You should use instead SomeFactory someFactory = mock(SomeFactory.class) and then follow the updated response of #DiscoS2
Let's say I have the following code:
protected int returnFourtyTwo() {
evilMethod(new Object, "");
return 42;
}
protected static void evilMethod(Object obj, String string) {
throw new RuntimeException("This is me being evil.");
}
What I'm trying to do is to run my returnFourtyTwo() method without throwing the runtime exception in my unit test. I've been able to use the suppress() method to bypass class constructors before just fine, but this is the first time I've had to bypass a static method (with more than one argument) in a non-static class. Unfortunately, resources on the topic are a bit scarce.
Your only way out is to mock the static method, as mentioned by #Dave. You can do that with PowerMock.
See Mocking static methods with Mockito.
Depending on how complicated your actual method implementation is, you could separate your return call from your exception throwing - then test on the return call which will not throw the exception. In a lot of cases it's best if strange ints such as 42 have their own variable anyway to explain what it corresponds too - If it is always 42, then it is static and final.
This is what I would do for your exact situation here, but I'm guessing this is a major simple abstraction from your actual problem so you probably still want to mock it as previously suggested.
static final int theAnswerToLife = 42;
protected int returnFourtyTwo() {
evilMethod(new Object, "");
return getTheAnswerToLife();
}
protected int getTheAnswerToLife() {
return theAnswerToLife;
}
protected static void evilMethod(Object obj, String string) {
throw new RuntimeException("This is me being evil.");
}
I don't say it is a good approach, but at least it works and it is not that bad.
you can do this :
create a public method in your inTest class and move your static method call there
in your unit test - you are testing inTest class - you can use a spy instead of mock for your inTest class
just ask unit test to do nothing for that method!
down side? we have a public method instead of private
Example :
I am unit testing the recyclerView Adapter :
I have a logger which has static method call so I moved all logs to a method
fun logMe(message: String) {
MyCrashAnalytics.leaveBreadcrumb(message)
}
and in unit test we have:
val underTest = MyAdapter(....)
then in tests or in setup method we can do this.
val spiedUnderTest = spy(underTest)
doNothing().`when`(spiedUnderTest).logMe(anyString())
Then we are good to go!
In simple you can use #Ignore annotation to your method.
I want to know if there is any technical difference between the following, when writing JUnit tests:
Option 1:
Define a setup method, i.e annotated with #Before, to initialize test fixture state before any #Test method is run.
Option 2:
Define a private method - just a plain old private method without any annotation - that does the same initialization, and make the first line of every #Test method a call to this method. (Ignore the possibility of someone forgetting to call the method in every test. I am looking for technical differences, not human factors)
Example of Option 2:
public class MyTest {
private void runSetupLogic() {
// whatever #Before method would have done
}
#Test
public void testMethod1() {
runSetupLogic();
// test logic
}
#Test
public void testMethod2() {
runSetupLogic();
// test logic
}
}
They are not really exactly the same, but for all intents and purposes either way should be fine. However, if you are interested in the technical analysis then my shaky understanding of the current JUnit 4 code on Github follows:
Here is what seems to be the actual code being ran when you use #Before using the default JUnit 4 runner src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java:
/**
* Returns a {#link Statement}: run all non-overridden {#code #Before}
* methods on this class and superclasses before running {#code next}; if
* any throws an Exception, stop execution and pass the exception on.
*/
protected Statement withBefores(FrameworkMethod method, Object target,
Statement statement) {
List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
Before.class);
return befores.isEmpty() ? statement : new RunBefores(statement,
befores, target);
}
The above calls RunBefores in src/main/java/org/junit/internal/runners/statements/RunBefores.java:
public class RunBefores extends Statement {
private final Statement next;
private final Object target;
private final List<FrameworkMethod> befores;
public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) {
this.next = next;
this.befores = befores;
this.target = target;
}
#Override
public void evaluate() throws Throwable {
for (FrameworkMethod before : befores) {
before.invokeExplosively(target);
}
next.evaluate();
}
The invokeExplosively method definition is in src/main/java/org/junit/runners/model/FrameworkMethod.java:
public Object invokeExplosively(final Object target, final Object... params)
throws Throwable {
return new ReflectiveCallable() {
#Override
protected Object runReflectiveCall() throws Throwable {
return method.invoke(target, params);
}
}.run();
}
which seems to use reflection to invoke the methods annotated with #Before.
Anyway, hope this answer is somewhat correct, but I'm not sure. If anyone has any corrections I can edit them in from the comments. By the way, for reference here is the javadoc for the #Before annotation: http://junit.org/javadoc/latest/org/junit/Before.html
I do not believe so.
However, if you were you implement another function, such as tearDown(), that would function essentially as an #After method, I would argue you might as well use them for readability, for the benefit of other collaborators or maybe even yourself.
The upside to using #Before and #After annotations is the that they avoid having to call a method at the beginning of each unit test, designed to save you the extra maintenance. If for some reason you had forgotten to add the call to your setUp() and/or tearDown() method, who knows what could go wrong.
This is, of course, if you need the EXACT SAME setup before each test. If you envision having a completely different setup for different unit tests, than perhaps you should look at the functionality of the class you are testing and ask yourself if perhaps you could modularize more.
The benifit comes from reporting.
In your method: runSetupLogic()
when ran from the start of a test, is reported within the test. Not as part of the setup and not as part of the initialization.
If the setup method fails, you get an accurate description of what failed... setup vs testing.
The before method allows you to isolate test failures from setup failures and allows the reporting solution to know as well.
I am using mockito as mocking framework. I have a scenerio here, my when(abc.method()).thenReturn(value) does not return value, instead it returns null.
public class DQExecWorkflowServiceImplTest {
#InjectMocks
DQExecWorkflowServiceImpl dqExecWorkflowServiceImpl = new DQExecWorkflowServiceImpl();
#Mock
private DQUtility dqUtility;
#Mock
private DqExec dqExec;
#Mock
private DqCntlDefn dqCntlDefn;
#Mock
private DqCntlWfDefn dqCntlWfDefn;
#Mock
private DqCntlWfDefnTyp dqCntlWfDefnTyp;
#Mock
private IDQControlWfDefTypeService controlWfDefTypeService;
#Before
public void setUp() throws Exception {
dqExec = new DqExec();
dqCntlWfDefn = new DqCntlWfDefn();
dqUtility = new DQUtility();
dqCntlWfDefnTyp = new DqCntlWfDefnTyp();
dqCntlWfDefnTyp.setDqCntlWfDefnTypCd("MIN_INCLUSIVE_VAL");
dqExecWorkflowServiceImpl
.setControlWfDefTypeService(controlWfDefTypeService);
}
#Test
public void testExecuteWorkflow() {
when(controlWfDefTypeService.getDqCntlWfDefnTypCd(dqCntlWfDefn))
.thenReturn(dqCntlWfDefnTyp);
dqExecWorkflowServiceImpl.executeWorkflow(dqExec, dqCntlWfDefn);
}
}
Java class
#Override
public DqCntlWfExec executeWorkflow(final DqExec dqExec,
final DqCntlWfDefn dqCntlWfDefn) {
final DqCntlWfExec dqCntlWfExec = new DqCntlWfExec();
dqCntlWfExec.setDqCntlWfExecEffDt(dqUtil.getDefaultEffectiveDt());
dqCntlWfExec.setDqCntlWfExecExpDt(dqUtil.getDefaultExpiryDt());
dqCntlWfExec.setDqCntlWfDefn(dqCntlWfDefn);
dqCntlWfExec.setDqExec(dqExec);
final DqCntlWfDefnTyp dqCntlWfDefnTyp = controlWfDefTypeService
.getDqCntlWfDefnTypCd(dqCntlWfDefn);
String workflowType = null;
if(null!=dqCntlWfDefnTyp){
workflowType = dqCntlWfDefnTyp.getDqCntlWfDefnTypCd();
}
When ever i run the test file the when is not working and i am using mockito1.8.5 jar in the buildpath. The service call is being mocked but returns the null value.
final DqCntlWfDefnTyp dqCntlWfDefnTyp = controlWfDefTypeService
.getDqCntlWfDefnTypCd(dqCntlWfDefn);
This object dqCntlWfDefnTyp is null
I have done this before and there was no problem with the when, It seems to be working with files i have done before. I had followed the same procedure for the test file but i couldnt figure out the issue. Can anyone please assist me
Thanks to all the folks in advance
Mockito mock works when we mock the objects loosely.
Here is the change i have made to make it work:
when(controlWfDefTypeService.getDqCntlWfDefnTypCd(any(DqCntlWfDefn.class))
.thenReturn(dqCntlWfDefnTyp);
Instead of passing the object of the Mock class, I passed the class with the Matcher any() and it works.
TL;DR If some arguments in your test are null, be sure to mock the parameter call with isNull() instead of any(SomeClass.class).
Explanation
This might not be the answer that helps OP, but might be useful for someone else. In my case the setup was all good, however, some mocks returned the desired thenReturn(...) value and some didn't.
It's important to understand, that the method call you're trying to mock (i.e. the method in when(someMock.methodToMock)) has to match the actual call and not the signature only.
In my case, I mocked a method with a signature:
public void SomeValue method(String string, SomeParam param)
The call however, in the test was something like:
method("some string during test", null);
Now if you mock the call with:
when(MockedClass.method(anyString(), any(SomeParam.class))
Mockito will not match it even though the signature is correct. The problem is that Mockito is looking for a call of method() with the arguments String and SomeParam, whereas the actual call was with a String and null. What you have to do is:
when(MockedClass.method(anyString(), isNull())
Hint
Since there are many isNull() implementations in different frameworks, be sure to use this one org.mockito.ArgumentMatchers.isNull.
I think I have found your issue, but not all the credit goes to me.
Since you are trying to mock 'dqCntlWfDefnTyp' in your test class and the object itself is being instantiated in the class that you are trying to test, you inevitably run into some issues. The primary problem is that the object cannot be mocked because it is being recreated in during the test.
There are a few options, but the best choice in my humble opinion is using PowerMockito. You will be able to replace the object within the class that is being tested with the one you mock.
An excellent example of this usage of PowerMockito from #raspacorp on this question:
public class MyClass {
void method1{
MyObject obj1=new MyObject();
obj1.method1();
}
}
And the test class...
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class MyClassTest {
#Test
public void testMethod1() {
MyObject myObjectMock = mock(MyObject.class);
when(myObjectMock.method1()).thenReturn(<whatever you want to return>);
PowerMockito.whenNew(MyObject.class).withNoArguments().thenReturn(myObjectMock);
MyClass objectTested = new MyClass();
objectTested.method1();
... // your assertions or verification here
}
}
I had the same problem. The solution for me was to put the Mockito.when(...).thenReturn(...); into the #Before-SetUp method.
Just like Younes EO said: it usually is related to null arguments being passed to mocked functions.
One thing worth adding is that if you're using Kotlin for your tests (and you have mockito-kotlin in your project), for Nullable arguments you should usually use anyOrNull() instead of any().
Relevant to the topic, just in case this helps someone. My mockito.when wasn't working when asserting anyString() reason being the String within the tested class was an injected value from a properties file. The following line set the injected value in the unit test:
ReflectionTestUtils.setField(bean, "theVariable", "theValue");
I haved the same problem when i make test for controler. Use #MockBean instead #Mock