I'm learning Mockito at the moment and one of the things I'm doing to consolidate my learning is converting an old JUnit test from using a hand rolled mock class to one which uses Mockito mocks instead. However, I've run into a situation I'm not sure how to handle.
Specifically, my unit under test constructs a String
which gets passed to the mocked object as a parameter in a method call on it. I'd like to test that the String
is constructed correctly. The challenge is that part of the String
is a hash key which is generated internally and changes on every invocation. One solution that would work would be to get the hash generation under my control and inject a dummy generator for test execution. However, this is a fair bit of work.
My old hand rolled mock class would store the arguments passed to it which I could query in my test. This allowed me to query the start and end of the String
via the following:
assertTrue(mockFtpClient.getFilePathAndName().startsWith("/data/inbound/XJSLGG."));
assertTrue(mockFtpClient.getFilePathAndName().endsWith(".pdf"));
This was a sufficent enough test for my taste. So my question is, is it possible using Mockito to query or get a hold of the arguments passed to a method so that i can perform something similiar to the above?
UPDATE 24/06/2011:
At this point I have excepted Gnon's answer. However, I have since discovered something which works better for me. Namely ArgumentCaptor
. Here's how it works:
ArgumentCaptor<String> fileNameArgument = ArgumentCaptor.forClass(String.class);
verify(mockFtpClient).putFileOnServer(fileNameArgument.capture());
assertTrue(fileNameArgument.getValue().startsWith(START_FILE_NAME) &&
fileNameArgument.getValue().endsWith(END_FILE_NAME));
The javadoc for Mockito state that ArgumentCaptor
is generally a better choice when you have a one-off specific argument matching requirement, as I do here.
Basically you need to use argThat() in Mockito, that lets you treat a Hamcrest Matcher as a verification argument. Here is the code you use to make custom assertions about a passed-in argument:
@Test
public void testname() throws Exception {
HashReceiver receiver = mock(HashReceiver.class);
receiver.set("hash");
verify(receiver).set(argThat(new HashMatcher()));
}
class HashMatcher extends BaseMatcher<String> {
@Override
public boolean matches(Object item) {
String hash = (String) item;
if (hash.startsWith("/data/inbound/XJSLGG.") && hash.endsWith(".pdf"))
return true;
return false;
}
}
// Mocked
class HashReceiver {
public void set(String hash) {
}
}
You may be able to use a generic matcher instead, or a combination of generic matchers.
Have a look at the accepted answer to this question mockito-how-to-make-a-method-return-an-argument-that-was-passed-to-it it will show you how to get a hold of the arguments passed to your mock method invocation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With