JMockit equivelant to Mockito doNothing() - java

In Mockito if you want a void method to do nothing you can do this:
doNothing().when(_mockedClass).voidMethod();
Is there a way to do this with JMockit?
I can't seem to find anything about it. I've been trying to switch to JMockit but am having trouble finding documentation for some of the things we do with Mockito. I suspect they are all there in one form or another, just having trouble finding them, so figured I'd start asking one question at a time here and hope there are easy answers! Thanks!

Just like with Mockito, actually, if you want a method to do nothing, then simply don't record an expectation for it. Alternatively, you can record an expectation with no result, but there is really no need for that (or a point to it).
(This would only not be the case when using strict expectations (with new StrictExpectations() {{ ... }}), in which case all method invocations need to be accounted for.)

Related

Verifying that Mockito.when calls are still needed

Over time, our tests have collected a whole bunch of Mockito.when calls. I'd like to know if there some that aren't needed any more. I tried doing
Mockito.verify(Mockito.when(someMock.someCall().return("foo").getMock(), Mockito.atLeastOnce());
But get
org.mockito.exceptions.misusing.UnfinishedVerificationException:
Missing method call for verify(mock) here:
Is there a way to accomplish this? I'd like to aspect in a way to check if these when()s are being used as there are far too many for a human to do by hand, so trying to get to figure out how to do this inline.
I could just duplicate the same call found in when() with a completely separate call to Mockito.verify(), but it is hard duplicate the when() call method and arguments call chain through aspects.
The built-in solution to the problem would be to use strict stubbing. There is an article over at Baelung explaining it.

Calling Mockito.when multiple times on same object?

When trying to use Mockito with Spring, by creating the Mock object via a bean declaration...
<bean id="accountMapper" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="org.example.persistence.mybatis.mappers.AccountMapper" />
</bean>
...I found some strange behavior when calling Mockito.when multiple times without reseting the Mock object, for example:
Mockito.when(this.accountMapper.createBadGrammarException()).thenThrow(new BadSqlGrammarException("Bla", null, new SQLException()));
As soon as this code (the "Mockito.when") is called multiple time during the test (on the same mock), the tests fails with an error (BadSqlGrammerException even if this exception was what was actually expected - I do get a failure if I don't throw the exception, and throwing it manually works fine). Is this expected behavior? Mockito seems to suggest creating a new mock every time, which would mean creating the DAO for each method...?
What exactly happens when I call the Mockito.when method two times? How should the mock react? Replace the behavior? Ignore it? Unfortunately most searches only yield results for how to return different results for multiple calls to the method itself, but not what is to be expected for multiple calls to Mockito.when...
I'm simply trying to understand Mockito and best practices here, because going with something just because it SEEMS to works seems to be a bad idea...
One of the problems with Mockito.when is that the argument you pass to it is the expression that you're trying to stub. So when you use Mockito.when twice for the same method call, the second time you use it, you'll actually get the behaviour that you stubbed the first time.
I actually recommend NOT using Mockito.when. There are many traps that you can fall into when you use it - quite a few cases when you need some other syntax instead. The "safer" alternative syntax is the "do" family of Mockito methods.
doReturn(value).when(mock).method(arguments ...);
doThrow(exception).when(mock).method(arguments ...);
doAnswer(answer).when(mock).method(arguments ...);
So in your case, you want
doThrow(new BadSqlGrammarException(??, ??, ??)).when(accountMapper).createBadGrammarException();
If you are starting out with Mockito, then I recommend that you learn to use the "do" family. They're the only way to mock void methods, and the Mockito documentation specifically mentions that. But they can be used whenever Mockito.when can be used. So if you use the "do" family, you'll end up with more consistency in your tests, and less of a learning curve.
For more information about the cases when you must use the "do" family, see my answer on Forming Mockito "grammars"
The simple answer is:
when you write Mockito.when(object.fooMethod()).then() then fooMethod() is actually called.
Another point is that we can't observe it first time, because it called on mocked object. But when we write when for the second time then we have some behavior for fooMethod() (we set it previously, in your case it Exception).
To check this better you can spy object:
Bar spyBar = Mockito.spy(Bar.class)
when(spyBar.fooMethod()).then()...
and fooMethod() will be actually called.

Mockito mock() and recording of invocation

I'm using Mockito in order to do some mocks/testing. My scenario is simple : I have a class mocked using mock() and I'm invoking this class (indirectly) for a large number of times (i.e. ~100k)
Mockito seems to hold some data for every invocation, and so I run out of memory at a certain point.
I'd like to tell mockito not to hold any data (I don't intend to call verify(), etc, I just don't care, for this specific tests, what reaches to that mock). I don't want to create new mocks with every invocation.
You can use Mockito.reset(mock), just be aware that after you call it, your mock will forget all stubbing as well as all interactions, so you would need to set it up again. Mockito's documentation on the method has these usage instructions:
List mock = mock(List.class);
when(mock.size()).thenReturn(10);
mock.add(1);
reset(mock);
//at this point the mock forgot any interactions & stubbing
They do also discourage use of this method, like the comments on your question do. Usually it means you could refactor your test to be more focused:
Instead of reset() please consider writing simple, small and focused test methods over lengthy, over-specified tests. First potential code smell is reset() in the middle of the test method. This probably means you're testing too much. Follow the whisper of your test methods: "Please keep us small & focused on single behavior". There are several threads about it on mockito mailing list.

Is there a better way to test the following methods without mocks returning mocks?

Assume the following setup:
interface Entity {}
interface Context {
Result add(Entity entity);
}
interface Result {
Context newContext();
SpecificResult specificResult();
}
class Runner {
SpecificResult actOn(Entity entity, Context context) {
return context.add(entity).specificResult();
}
}
I want to see that the actOn method simply adds the entity to the context and returns the specificResult. The way I'm testing this right now is the following (using Mockito)
#Test
public void testActOn() {
Entity entity = mock(Entity.class);
Context context = mock(Context.class);
Result result = mock(Result.class);
SpecificResult specificResult = mock(SpecificResult.class);
when(context.add(entity)).thenReturn(result);
when(result.specificResult()).thenReturn(specificResult);
Assert.assertTrue(new Runner().actOn(entity,context) == specificResult);
}
However this seems horribly white box, with mocks returning mocks. What am I doing wrong, and does anybody have a good "best practices" text they can point me to?
Since people requested more context, the original problem is an abstraction of a DFS, in which the Context collects the graph elements and calculates results, which are collated and returned. The actOn is actually the action at the leaves.
It depends of what and how much you want your code to be tested. As you mentionned the tdd tag, I suppose you wrote your test contracts before any actual production code.
So in your contract what do you want to test on the actOn method:
That it returns a SpecificResult given both a Context and an Entity
That add(), specificResult() interactions happen on respectively the Context and the Entity
That the SpecificResult is the same instance returned by the Result
etc.
Depending on what you want to be tested you will write the corresponding tests. You might want to consider relaxing your testing approach if this section of code is not critical. And the opposite if this section can trigger the end of the world as we know it.
Generally speaking whitebox tests are brittle, usually verbose and not expressive, and difficult to refactor. But they are well suited for critical sections that are not supposed to change a lot and by neophytes.
In your case having a mock that returns a mock does look like a whitebox test. But then again if you want to ensure this behavior in the production code this is ok.
Mockito can help you with deep stubs.
Context context = mock(Context.class, RETURNS_DEEP_STUBS);
given(context.add(any(Entity.class)).specificResult()).willReturn(someSpecificResult);
But don't get used to it as it is usually considered bad practice and a test smell.
Other remarks :
Your test method name is not precise enough testActOn does tell the reader what behavior your are testing. Usually tdd practitioners replace the name of the method by a contract sentence like returns_a_SpecificResult_given_both_a_Context_and_an_Entity which is clearly more readable and give the practitioner the scope of what is being tested.
You are creating mock instances in the test with Mockito.mock() syntax, if you have several tests like that I would recommend you to use a MockitoJUnitRunner with the #Mock annotations, this will unclutter a bit your code, and allow the reader to better see what's going on in this particular test.
Use the BDD (Behavior Driven Dev) or the AAA (Arrange Act Assert) approach.
For example:
#Test public void invoke_add_then_specificResult_on_call_actOn() {
// given
... prepare the stubs, the object values here
// when
... call your production code
// then
... assertions and verifications there
}
All in all, as Eric Evans told me Context is king, you shall take decisions with this context in mind. But you really should stick to best practice as much as possible.
There's many reading on test here and there, Martin Fowler has very good articles on this matter, James Carr compiled a list of test anti-patterns, there's also many reading on using well the mocks (for example the don't mock types you don't own mojo), Nat Pryce is the co-author of Growing Object Oriented Software Guided by Tests which is in my opinion a must read, plus you have google ;)
Consider using fakes instead of mocks. It's not really clear what the classes in question are meant to to, but if you can build a simple in-memory (not thread-safe, not persistent etc) implementation of both interfaces, you can use that for flexible testing without the brittleness that sometimes comes from mocking.
I like to use names beginning mock for all my mock objects. Also, I would replace
when(result.specificResult()).thenReturn(specificResult);
Assert.assertTrue(new Runner().actOn(entity,context) == specificResult);
with
Runner toTest = new Runner();
toTest.actOn( mockEntity, mockContext );
verify( mockResult ).specificResult();
because all you're trying to assert is that specificResult() gets run on the right mock object. Whereas your original assert doesn't make it quite so clear what is being asserted. So you don't actually need a mock for SpecificResult. That cuts you down to just one when call, which seems to me to be about right for this kind of test.
But yes, this does seem frightfully white box. Is Runner a public class, or some hidden implementation detail of a higher level process? If it's the latter, then you probably want to write tests around the behaviour at the higher level; rather than probing implementation details.
Not knowing much about the context of the code, I would suggest that Context and Result are likely simple data objects with very little behavior. You could use a Fake as suggested in another answer or, if you have access to the implementations of those interfaces and construction is simple, I'd just use the real objects in lieu of Fakes or Mocks.
Although the context would provide more information, I don't see any problems with your testing methodology myself. The whole point of mock objects is to verify calling behavior without having to instantiate the implementations. Creating stub objects or using actual implementing classes just seems unnecessary to me.
However this seems horribly white box, with mocks returning mocks.
This may be more about the class design than the testing. If that is the way the Runner class works with the external interfaces then I don't see any problem with having the test simulate that behavior.
First off, since nobody's mentioned it, Mockito supports chaining so you can just do:
when(context.add(entity).specificResult()).thenReturn(specificResult);
(and see Brice's comment for how to do enable this; sorry I missed it out!)
Secondly, it comes with a warning saying "Don't do this except for legacy code." You're right about the mock-returning-mock being a bit strange. It's OK to do white-box mocking generally because you're really saying, "My class ought to collaborate with a helper like <this>", but in this case it's collaborating across two different classes, coupling them together.
It's not clear why the Runner needs to get the SpecificResult, as opposed to whatever other result comes out of context.add(entity), so I'm going to make a guess: the Result contains a result with some messages or other information and you just want to know whether it's a success or failure.
That's like me saying, "Don't tell me all about my shopping order, just tell me that I made it successfully!" The Runner shouldn't know that you only want that specific result; it should just return everything that came out, the same way that Amazon shows you your total, postage and all the things you bought, even if you've shopped there lots and are perfectly aware of what you're getting.
If some classes regularly use your Runner just to get a specific result while others require more feedback then I'd make two methods to do it, maybe called something like add and addWithFeedback, the same way that Amazon let you do one-click shopping by a different route.
However, be pragmatic. If it's readable the way you've done it and everyone understands it, use Mockito to chain them and call it a day. You can change it later if you have need.

Customize formatting of passed-in parameter in an expectation

I'm using jmock to mock out an OutputStream and set expectations on the data that gets written to it.
So I have an expectation that looks something like this
oneOf(stream).write(byteArrayMatching("Some string"));
(byteArrayMatching) is a factory for a custom matcher.
This all works fine, except when the test fails because the class under test writes incorrect data, I get an error looking something like this:
java.lang.AssertionError: unexpected invocation: stream.write([<60>, <63>, ...])
It's pretty hard to identify what exactly is wrong with the data by looking at the sequence of bytes (I haven't gotten around to memorizing ASCII yet). This pretty much forces me to run the test in a debugger to figure out what's wrong.
My question is: is there a way to somehow register a formatter of sorts with the mock object or the Mockery object which can pretty print a parameter value? It's clear that jmock is already doing some pretty-printing, since the above is not the output of byte[].toString(), but I can't find anything in the API docs that suggests a way to customize this pretty-printing logic
There is no way to currently do this in the current (2.5.1) jMock library. I would suggest you log an enhancement to jMock.
The cute answer is that mocking makes more sense against a type that you've defined, that has some domain structure to it, rather than external API.
The next answer is to look at the new version of Hamcrest which includes support for reporting a mismatch.
The next answer, unless there's sequence involved, is that in this case it might be better to use an in-memory byte stream and assert the string afterwards.
And file an issue too, please :)

Categories

Resources