I have the following code:
when(mockedOperation.getResult(anyDouble(), anyDouble())).thenCallRealMethod();
when(mockedOperation.division(anyDouble(), not(eq(0d)))).thenCallRealMethod();
Where Operation is something like Command pattern - it encapsulates some concrete action, in this case, simplified - division operation. The result retrieval happens not directly, but by the means of contract method, say getResult(arg1, arg2). So, I call
mockedOperation.division(10d, 3d);
But (from debugging info in my concrete implementation of Operation) I can see that division() gets not 10 and 3 but (0, 0).
As far as I understand, that arguments are lost somewhere between the thenCallRealMethod() by getResult() and calling real division() afterwards.
What is the reason for that behavior and how should I implement partial mocks correctly in case I really need it?
UPD. Maybe I should try to say it another way, for example, simply how do you create mocks that callRealMethod in such a way that arguments are correctly delivered to the endpoint?
OK, the problem is solved now. Turns out I just encountered another undocumented feature/bug in Mockito (or just the feature I didn't find the docs for yet). The problem was that in my #Before I also mocked that very operation, and, as it appears, when one redefines mock, something black-magical happens and the result is as I've already described - arguments are somehow lost.
Related
Not quite sure what the formal term for such a pattern/problem, but here is what I'm facing:
I have an operation that is somewhat large. It can either pass or fail. Each pass or fail carries with it either the result of the successful operation, or information about why the operation failed. I am struggling to architect this function 'correctly'.
class Pass{
int someGoodStuff;
double someOtherGoodStuff;
}
class Fail{
String failureMsg;
float howMuchOperationWasOffBy;
}
class Operator{
public ??? operation(){
}
}
Approach 1: Fail states are like exceptions. Lets throw them. This allows me to include the failure information and make the return type just Pass. However, these fail states are not programming language errors, they are business logic fails. So, two things sit wrong with me about this approach: one, it confuses business logic fails with actual Java errors (which seems wrong) and two, it coopts the normal flow of execution without any really good reason to do so.
Approach 2: Functions in java like to return one object type, so have Pass and Fail both implement an interface Result, and have the return type of the function be that.
interface Result{...}
class Pass implements Result{...}
class Fail implements Result{...}
class Operator{
public Result operation(){...}
}
However, the pass and fail states that the function returns are completely different. They have little to no overlapping variables or functions. This seems wrong and reduces me to have to instanceof all the important information out of the passes and fails.
Approach 3: Some sort of union object that can be either pass or fail (but not both)
class Result{
public Pass pass=null;
public Fail fail=null;
}
class Operator{
public Result operation(){...}
}
This has the advantage that I can say things like
Result result=op.operation();
if (result.succeed()){
doStuffWithPass(result.getPass());
}else{
doStuffWithFail(result.getFail());
}
Which is basically what I was doing with instanceof, but nicer looking; the code now looks how you might expect it to. It is clear to follow.
However, Java has no real Union types. I have to make sure someone doesn't accidentally try to mess with the pass variables of a fail Result or vice versa. Furthermore, every method I call on the union type have to be predicated with figuring out whether it is a pass or fail (That If branch suddenly has to be everywhere)
Finally, although not a real concern yet, such a pattern I believe allocates space for both a Pass and a Fail for each Result, when I know that it can only ever be one of them (ie it should take up a space equal to Max(space(Pass),space(Fail)))
None of these approaches seems perfect. I feel like there should be a pattern to solve this kind of problem. Is there?
In this case Error thrown Approach Seems to be best.
Reasons
You can create multiple Custom Exceptions for multiple type and when there is anything wrong happens. By this approach you make sure that whenever something bad happen your program returns the control with specified error.
As a return type you can return your Result with specific value. So whenever your program return something it seems working or pass.
This question already has answers here:
How does mockito when() invocation work?
(2 answers)
Closed 5 years ago.
I know I don't really need to know how Mockito does everything under the hood in order to be able to use it, but this has been perplexing me for a while so more than anything I'm curious to understand it. There are several Mockito methods that I can't understand how they could possibly work. One good example is:
OngoingStubbing<T> Mockito.when(T methodCall)
You can use this to do things like:
Object mockedObject = Mockito.mock(Object.class);
Mockito.when(mockedObject.toString()).thenReturn("super cool string");
System.out.println(mockedObject.toString());
This code would give the output:
super cool string
I understand how to use this, but I don't understand how this could possibly work. How does Mockito.when know what mock object and method we are concerned with? As far as I know, we aren't passing in mockedObject, we are passing in mockedObject.toString() which is a value of type String. I'm pretty sure that prior to setting up all of the "when/thenReturn" stuff, mockedObject.toString() just returns null. So why isn't this the same as doing:
Object mockedObject = Mockito.mock(Object.class);
mockedObject.toString();
Mockito.when(null).thenReturn("super cool string");
System.out.println(mockedObject.toString());
Obviously the second code segment doesn't make any sense, but it seems like the two code segments should be functionally equivalent.
EDIT:
The two code segments actually are the same. See my answer to my own question below.
Doh!
I guess I should have actually tried to run my sample code before I posted this question.
It turns out that the two code segments actually are equivalent. I just assumed that they weren't.
This revelation sheds some light into how Mockito.when is implemented under the hood.
My best guess now, is that when mockedObject is mocked, part of the newly created implementation of Object.toString() records that the .toString() method was called (this has to be done anyway in order to get Mockito.verify() to work). It must then record this call to a mock method in some sort of thread local static variable. Then when I call when(), it actually ignores the input value (except perhaps for using its type?) and then searches for whatever mocked method was most recently called on any of the mock objects that exist in that thread (or perhaps only the method calls that match that signature). Whatever method was last called is the one that it decides to modify.
This of course just my guesses based on how I've observed mockito's functionality. The actual implementation may be different, but this at least makes sense.
I'm having great fun with the method delegation described here:
http://www.javacodegeeks.com/2015/01/make-agents-not-frameworks.html
This works nicely:
.intercept(MethodDelegation.to(LogInterceptor.class)
.andThen(SuperMethodCall.INSTANCE)
I can intercept calls and capture arguments passed to methods, which is half of what I want to achieve. However, I haven't found an equally succinct way of capturing the return value. I know I can get a Callable passed to the interceptor which performs the call, but going down that road seems like a sure way to mess up my stacktraces.
It seems to me there should be an easy and canonical-ish way to implement the "around-method" pattern.
Before I start digging into the APIs for reals: Am I missing something?
No, you are not missing anything.
Whenever you manipulate code with Byte Buddy, this manipulation will be reflected by the stack traces of your application. This is intentional as it makes debugging much easier in case that something goes wrong. Think of your log interceptor throwing a runtime exception; if the intercept was somehow merged into your original method, this would be quite confusing for other developers to figure out. With Byte Buddy's approach, you can simply navigate to the causing source as your interceptor is in fact available from there. With Byte Buddy, no exception is ever thrown from generated code such that any problem can be traced back to source code.
Also, merging stack frames can have strange side-effects to caller sensitive code. For example, a security manager might give higher permissions to an interceptor than to the intercepted code. Merging stack frames would revert these permissions.
Writing an interceptor with a #Super Callable injected is the canonical way for implementing arround-advice. Do not worry about performance either. Byte Buddy is written in a way that makes it very easy for the JIT compiler to inline code such that the super method call is most likely executed with zero overhead. (There is even a benchmark demonstrating that.) For your example, generic arround-adivce would look like the following:
public class TimingInterceptor {
#RuntimeType
public static Object intercept(#Super Callable<?> zuper)
throws Exception {
long before = System.currentTimeMillis();
try {
return zuper.call();
} finally {
System.out.println("Took: " + (Systen.currentTimeMillis() - before));
}
}
}
For every method, the time it takes to execute is now printed to the console. You delegate to this code using MethodDelegation.to(TimingInterceptor.class).
Make sure that you use the #RuntimeType annotation. This way, Byte Buddy attempts a casting at runtime, making this generic interception possible.
I am attempting to set up a when statement for a method used inside another method I am testing. Inside the method I am testing I am creating a list which I have no reference to, therefore I cannot mock it. I would like to validate the contents of this list when it is used in the above mentioned method inside. I have used the following as part of the when method, but ended up with an "InvalidUseOfMatchersException" in every case. What am I missing?
Matchers.eq(mockKeys) //mockKeys is a List<String> with expected contents
Matchers.anyListOf(String.class)
Mockito.when(myDaoImpl.getRecords([either of the above])).thenReturn(mockResult);
I must refuse to provide exact code.
List<String> mockKeys = createMockKeys(); // defined elsewhere
when(myDaoImpl.getRecords(Matchers.eq(mockKeys))).thenReturn(mockResult);
when(myDaoImpl.getRecords(mockKeys)).thenReturn(mockResult); // implicitly equal
when(myDaoImpl.getRecords(Matchers.anyListOf(String.class)))
.thenReturn(mockResult);
All of the above are fine. Nothing you've posted looks inherently wrong; it's more likely a problem we can't see, such as if getRecords is final, or in a use of Mockito or Matchers surrounding your code. Though it is understandable not to be able to post more code than you can, it may make it hard to provide a more-specific answer.
For the sake of debugging, place a call to Mockito.validateMockitoUsage() before and after your stub. This will help ensure that the problem is actually on the line you think it is, and not pollution from calls before or after.
Your problem is the two lines Matchers.eq(mockKeys); and Matchers.anyListOf(String.class). As the message says, you're using them invalidly.
Mockito uses its own data structure to store a matcher when you call such a method, but returns a different value from the actual call. That additional value must be passed to the method that you're stubbing (getRecords in this case), and when you stub, Mockito retrieves the actual matchers from the data structure.
Unless you completely understand how the data structure works, and know exactly what you're doing, you really need to put the calls to the two Matchers methods inside the call to getRecords. For example,
when(myDaoImpl.getRecords(eq(mockKeys), anyListOf(String.class))).thenReturn(mockResult);
Suppose that you have the following logic in place:
processMissing(masterKey, masterValue, p.getPropertiesData().get(i).getDuplicates());
public StringBuffer processMissing(String keyA, String valueA, Set<String> dupes) {
// do some magic
}
I would like to write a jUnit test for processMissing, testing its behavior in event dupes is null.
Am i doing the right thing here? Should I check how method handles under null, or perhaps test method call to make sure null is never sent?
Generally speaking, what is the approach here? We can't test everything for everything. We also can't handle every possible case.
How should one think when deciding what tests to write?
I was thinking about it as this:
I have a certain expectation with the method
Test should confirm define my expectation and confirm method works under that condition
Is this the right way to think about it?
Thanks and please let me know
First, define whether null is a valid value for the parameter or not.
If it is, then yes, definitely test the behavior of the method with null.
If it is not, then:
Specify that constraint via parameter documentation.
Annotate that constraint on the parameter itself (using an annotation compatible with the tool below).
Use a static analysis tool to verify that null is never passed.
No unit test is required for the invalid value unless you're writing code to check for it.
The static analysis tool FindBugs supports annotations such as #NonNull, with some limited data-flow analysis.
I personally think it would be unnecessarily expensive within large Java codebases to always write and maintain explicit checks for NULL and corresponding, non-local unit tests.
If you want to ensure that people don't call your API with a null argument you may want to consider using annotations to make this explicit, JSR 305 covers this, and its used in Guava. Otherwise you're relying on users reading javadoc.
As for testing, you're spot on in that you can't handle every possible case, assuming you don't want to support null values, I'd say that you may want to throw an IllegalArguemntException rather than a NullPointerException so you can be explicit about what is null, then you can just test for that exception being thrown - see JUnit docs.