So I'm trying to test a method methodUnderTest which is something like this:
methodUnderTest{
//Other stuff that works nice
this.setterMethod(OtherClass.methodThatErrors(arg1));
}
So I'm trying to avoid that static method call methodThatErrors.
What I'm doing so far:
ClassUnderTest spy = Mockito.spy(objectOfClassUnderTest);
Mockito.doNothing().when(spy).setterMethod(Mockito.any(OtherClass.class));
However this does not work, the method is still being called. I would've thought that it shouldn't call the argument method at all because I've written any for the argument of setterMethod. So how can I prevent this call using Mockito, not PowerMockito.
Edit:
So I managed to mock it by moving the static method call like so:
methodUnderTest{
this.extraSetterMethod(arg1);
}
extraSetterMethod(arg1){
this.setterMethod(OtherClass.methodThatErrors(arg1));
}
I don't really like this solution because it's adding several extra lines of code (even more with javadoc) which just makes the class messier.
The problem here is that the value is coming directly from the static method, and not the setter itself. Whatever value it's getting is coming from the real invocation of the method itself. Mocking out the call to the setter has no effect; it's not the result of the setter that's in error.
This is a scenario in which you have to make a hard decision:
Introduce a parameter to the method so that the call can be easier to mock, or
Use PowerMockito to mock out the call.
I strongly encourage the latter, especially if you're dealing with a legacy code base which is not very forgiving to a signature change.
Related
I am using junit to run a few unit tests. One of these calls a method in an object that I mock using mockito like;
#Mock
private MyClass myClass;
I then set up mockito to do something like
Mockito.when(myClass.foo(Mockito.any()).thenReturn(bar);
Now myClass.foo actually takes another one of my classes (say class Person) as an argument and what I would like to do is something like this
Mockito.when(myClass.foo(Person parson)).thenDo(person.setName("Name")).thenReturn(bar);
That is of course pseudo code but I hope it illustrates what I am trying to do. Is this possible?
You need to use thenAnswer or its twin doAnswer method.
See Mockito : doAnswer Vs thenReturn
You should use thenReturn or doReturn when you know the return value at the time you mock a method call. This defined value is returned when you invoke the mocked method.
Answer is used when you need to do additional actions when a mocked method is invoked, e.g. when you need to compute the return value based on the parameters of this method call.
If your answers become too complicated, consider using a fake instead of a mock.
In this case if your goal is to set field of Person object you can do that before or after the line:
Mockito.when(myClass.foo(Mockito.any()).thenReturn(bar);
doAnswer() would help do operations based on input, but operations would be performed on copy of arguments not the original arguments.
I have tested that incredible feature provided by whenNew some days ago, that allows us to "intercept" constructor calls of any class inside tested environment and return eg. mocked instance of given class. I was wondering what are principles behind this? My first thought was a bytecode manipulation in order to inject proper code blocks to contructor but hey - constructors does not return created instance so this is obviously not an answer.
What would it be then? AOP - intercepting contructor calls and replacing it with return given object statements?
Powermock modifies the bytecode in the calling class (the one with new SomeMockedClass(...)) so that it recovers and uses the mock instance passed into whenNew.
This is not the only way it could be implemented by a mocking library, though. JMockit also mocks constructors, but it does it by modifying the actual constructor instead (which still returns void, of course).
I am working on junit and using PowerMockRunner to mock static methods.
I am aware that static methods can be mocked using when(...).thenReturn(...)
I need to mock a certain method that takes four arguments:
public static void addInputPath(String, Boolean, Integer, Double)
I need the third parameter(Integer) in any call to this method to be replaced by, say 10. All other parameters should just be passed as is.
In other words, I need to do something like this:
when(addInputPath(str, bool, intgr, dbl)).thenReturn(addInputPath(str, bool, 10, dbl));
Is there a way to do this?
So, when I get your requirements right, what you actually want to do is to intercept the call to addInputPath() and invoke it with a different parameter?
If so: I am not sure if this can be done with any mocking framework (and I doubt that it is possible). Mocking frameworks are about mocking calls; not about instrumenting/intercepting calls.
Coming back to your problem, this is a nice example why static calls far too often cause problems. Thus, the best solution in my eyes would be to change your method xyz() to avoid that thing calling addInputPath() directly. Like this:
interface InputPathAdder {
void addInputPath(str, ... );
}
class ForwardingInputPathAdder implements InputPathAdder {
// implements the method by calling the static method
and all of a sudden, you can also do:
class ForwardingInputPathAdderWithFixedIntegerParm implements InputPathAdder {
// implements the method by calling the static method, but using 10 always
( obviously, naming could be improved here )
And now: you use dependency injection to give your "class under test" some Object implementing InputPathAdder. This could be either one that is completely mocked for testing; or it could be one that just does forwarding (in your production environment; or it could be the one that fixes the 3rd parameter). And no need for mocking for your "intercept" situation.
This seems like it should be simple but I'm running around in circles.
I have:
#Mock
SimpleAbstractCacheWithInputs<Key, Value, Inputs> underlyingCache;
I then try to set up a call on the cache in setup():
when(underlyingCache.getOrCreate(usdgbpKey)).thenReturn(usdgbpCfi);
But this throws a null pointer exception from within getOrCreate() because it's trying to execute the actual code in the real object, not mocked at all, and that isn't set up.
But I don't want to ever run getOrCreate real code, I just want it to return the mocked value!
So how do I do this without having to set up everything inside underlyingCache that I'm never going to use in order to mock this one method call?
If you were concerned about the behavior of a spy or already-stubbed object, I would recommend this syntax, which doesn't rely on calling the mocked object:
doReturn(usdgbpCfi).when(underlyingCache).getOrCreate(usdgbpKey);
...but that all seems right. If you're using the #Mock annotation, then the entire object should be mocked, or null if you've forgotten a Mockito runner/rule/initialization.
There are a few cases where mocking would fail and you get the actual behavior instead:
If the method is final, because then Mockito can't override the method (through a proxy).
If the class is final, because then Mockito can't override the class (through a proxy).
If the class has complicated access semantics, such as a public nested class that accesses private parent methods, because the Java compiler may rewrite the method call through a synthetic method that Mockito can't (easily) mock.
So I am using easymock to write unit test fpr a method inside my class. I have mocked an object inside this method and it works fine. The problem is inside this test method I have several calls to other methods inside the same class.
For example,
public class testClass {
public void testMethod() {
mockedObject.method(); --> I define a return type for this and it works fine.
this.otherMethod() {
--> Inside this method I have a call to the mocked object with different methods..
}
}
So my question is that, when the method calls another method by using this.otherMethod() should I define all the return values for the mockedObject calls inside otherMethod? Isn't there a way to specify a return value for otherMethod so that it won't even go inside the other method? Plz note that here this is not the mockedObject and that is why I cannot use eaymock return value for that. I was thinking maybe there might be a way around this.
Thanks.
Update: I found this for partial mocking of methods: http://www.easymock.org/EasyMock2_2_2_ClassExtension_Documentation.html
Which helps to only mock specific methods. But when I try to use it, it crosses a line on createMock method.. Sth like wrong syntax!
Thanks everyone,
I found this link: http://fczaja.blogspot.com/2011/11/easymock-create-partial-mocks.html
The answer is to partially mock those methods called within this method to isolate those method calls.
Thanks again.