I can't figure out what is wrong with this, hopefully someone can help:
I have an enum, MyEnum that is used as a parameter to a method I am trying to mock. The mocking looks a bit like this:
when(myMockedObject.getMethod(MyEnum.XYZ)).thenReturn(myMockedValue);
and the actual code execution looks like this:
MyMockedValue theMockedValue = myMockedObject.getMethod(MyEnum.XYZ);
I'm expecting theMockedValue to equal myMockedValue. However, the mocking is not working and theMockedValue is always null. What is wrong with this?
This was down to my own dodgy code. I found a duplicated mock object, one instance was involved in the mocking and the other was being used in the code, resulting in null values being returned.
Just as I thought I was losing the battle with mockito and now I realise I do understand what is going on.
Related
It seems that, when I use thenReturn like this:
when(abc.call()).thenReturn(a).thenReturn(b),
I expect:
verify(abc, times(2)).call()
instead, the method seems only get called once, I am a little confused(my test work as expected, the mock seems return the value I expected), but for the invocation times, I don't know if I am getting the wrong result, or it's a expected behavior of the Mockito?
when() is mocking the abc.call() method which has to produce a certain return type. If the method is called once, it will return the value also once, so the stubbing for method invocation is done only once hence the verify only recognizes one call.
You need to customize your function so that the stub(abc.call()) gets called more than once.
You can follow this thread for implementing multiple stubs
I'm trying to verify that the class I'm testing calls the correct dependency class's method. So I'm trying to match the method parameters, but I don't really care about the actual values in this test, because I don't want to make my test brittle.
However, I'm running into trouble setting it up because Mockito has decided that the behaviour I'm expecting is a bug: https://github.com/mockito/mockito/issues/134
So what't the correct way to define an ArgumentMatcher for a parameter that might be null?
With issue #134 "fixed", this code fails because the matchers only match in the first case. How can I define a matcher to work in all 4 cases?
MyClass c = mock(MyClass.class);
c.foo("hello", "world");
c.foo("hello", null);
c.foo(null, "world");
c.foo(null, null);
verify(c, times(4)).foo(anyString(), anyString());
From the javadocs of any()
Since Mockito 2.1.0, only allow non-null String. As this
is a nullable reference, the suggested API to match
null wrapper would be isNull(). We felt this
change would make tests harness much safer that it was with Mockito
1.x.
So, the way to match nullable string arguments is explicit declaration:
nullable(String.class)
I got this to work by switching to any(String.class)
I find this a bit misleading, because the API seems to suggest that anyString() is just an alias for any(String.class) at least up till the 2.0 update. To be fair, the documentation does specify that anyString() only matches non-null strings. It just seems counter-intuitive to me.
How about:
verify(c, times(4)).foo(anyObject(), anyObject());
Does that work for you?
Matchers.anyObject() allows for nulls.
Reference in Mockito docs:
I am mocking an interface array which throws java.lang.IllegalArgumentException: Cannot subclass final class class.
Following are the changes I did.
Added the following annotations at class level in this exact order:
#Runwith(PowerMockRunner.class)
#PrepareForTest({ Array1[].class, Array2[].class })
Inside the class I am doing like this:
Array1[] test1= PowerMockito.mock(Array1[].class);
Array2[] test2= PowerMockito.mock(Array2[].class);
and inside test method:
Mockito.when(staticclass.somemethod()).thenReturn(test1);
Mockito.when(staticclass.somediffmethod()).thenReturn(test2);
Basically I need to mock an array of interfaces.
Any help would be appreciated.
Opening up another perspective on your problem: I think you are getting unit tests wrong.
You only use mocking frameworks in order to control the behavior of individual objects that you provide to your code under test. But there is no sense in mocking an array of something.
When your "class under test" needs to deal with some array, list, map, whatever, then you provide an array, a list, or a map to it - you just make sure that the elements within that array/collection ... are as you need them. Maybe the array is empty for one test, maybe it contains a null for another test, and maybe it contains a mocked object for a third test.
Meaning - you don't do:
SomeInterface[] test1 = PowerMock.mock() ...
Instead you do:
SomeInterface[] test1 = new SomeInterface[] { PowerMock.mock(SomeInterface.class) };
And allow for some notes:
At least in your code, it looks like you called your interface "Array1" and "Array2". That is highly misleading. Give interfaces names that say what their behavior is about. The fact that you later create arrays containing objects of that interface ... doesn't matter at all!
Unless you have good reasons - consider not using PowerMock. PowerMock relies on byte-code manipulation; and can simply cause a lot of problems. In most situations, people wrote untestable code; and then they turn to PowerMock to somehow test that. But the correct answer is to rework that broken design, and to use a mocking framework that comes without "power" in its name. You can watch those videos giving you lengthy explanations how to write testable code!
Wanted but not invoked: However, there were other interactions with this mock:
This is a mockito error you would catch when trying to verify the invocation on an object on specific method, but what happens is you have interacted with other method of that object but not the one mentioned.
If you have an object named CustomerService and say it has two methods named saveCustomer() and verifyExistingCustomer(),
and your mockito looks something like verify(customerService, atleast(1)).verifyExistingCustomer(customer), but in your actual service you called the saveCustomer() at least one.
Any idea how to resolve this ?
From what you are describing, it looks like you are telling your mocks that you are expecting verifyExistingCustomer() to be called but you are not actually calling it.
You should probably look at your test design, specifically ensuring that you can (via mocking) isolate your tests to test each method individually.
If there is something in your code that decides whether to call saveCustomer() or verifyExistingCustomer() then you should try to mock the data that the code inspects so that you can test each individually.
For example if your code looked like this:
if (customer.getId() == 0) {
saveCustomer(customer);
} else {
verifyExistingCustomer(customer);
}
Then you could have two separate tests that you could isolate by setting a zero value and non-zero value for the id in customer.
If you'd like to share your code I could probably give you a better example.
In my attempt to mock an object in Groovy using the mock.interceptor package:
def mock = new MockFor(TheClass);
mock.demand.theMethod{ "return" }
mock.use {
def underTest = new TheClass()
println underTest.theMethod()
}
The problem I have is when creating TheClass() in the use{ block, it uses the actual constructor which, in this circumstance, I'd rather it not use. How can I create an instance of this class so I can test the method I do care about, theMethod, without needing to use the constructor?
Using EasyMock/CE, mocks can be made without using the constructor, but am curious how to achieve that in Groovy.
I recently saw a presentation by the author of GMock and it has some hooks to allow "constructor" mocking which I think is what you are after.
e.g.
def mockFile = mock(File, constructor('/a/path/file.txt'))
This library differs from that "built in" to groovy, however it looked very well written, with some thought put into the kinds of things you want to mock and more importantly the error messages you would get when tests should fail.
I think this is what you are after. I would say use constructor mocking with care - it could be a smell that you should inject a Factory object, but for some things it looked to work well.
You can use the interceptConstruction flag when calling MockFor, see
MockFor.