Simulate first call fails, second call succeeds - java

I want to use Mockito to test the (simplified) code below. I don't know how to tell Mockito to fail the first time, then succeed the second time.
for(int i = 1; i < 3; i++) {
String ret = myMock.doTheCall();
if("Success".equals(ret)) {
log.write("success");
} else if ( i < 3 ) {
log.write("failed, but I'll try again. attempt: " + i);
} else {
throw new FailedThreeTimesException();
}
}
I can setup the success test with:
Mockito.when(myMock).doTheCall().thenReturn("Success");
And the failure test with:
Mockito.when(myMock).doTheCall().thenReturn("you failed");
But how can I test that if it fails once (or twice) then succeeds, it's fine?

From the docs:
Sometimes we need to stub with different return value/exception for the same method call. Typical use case could be mocking iterators. Original version of Mockito did not have this feature to promote simple mocking. For example, instead of iterators one could use Iterable or simply collections. Those offer natural ways of stubbing (e.g. using real collections). In rare scenarios stubbing consecutive calls could be useful, though:
when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException())
.thenReturn("foo");
//First call: throws runtime exception:
mock.someMethod("some arg");
//Second call: prints "foo"
System.out.println(mock.someMethod("some arg"));
So in your case, you'd want:
when(myMock.doTheCall())
.thenReturn("You failed")
.thenReturn("Success");

The shortest way to write what you want is
when(myMock.doTheCall()).thenReturn("Success", "you failed");
When you supply mutiple arguments to thenReturn like this, each argument will be used at most once, except for the very last argument, which is used as many times as necessary. For example, in this case, if you make the call 4 times, you'll get "Success", "you failed", "you failed", "you failed".

Since the comment that relates to this is hard to read, I'll add a formatted answer.
If you are trying to do this with a void function that just throws an exception, followed by a no behavior step, then you would do something like this:
Mockito.doThrow(new Exception("MESSAGE"))
.doNothing()
.when(mockService).method(eq());

I have a different situation, I wanted to mock a void function for the first call and run it normally at the second call.
This works for me:
Mockito.doThrow(new RuntimeException("random runtime exception"))
.doCallRealMethod()
.when(spy).someMethod(Mockito.any());

To add on to this and this answer, you can also use a loop to chain the mocked calls. This is useful if you need to mock the same thing several times, or mock in some pattern.
Eg (albeit a farfetched one):
import org.mockito.stubbing.Stubber;
Stubber stubber = doThrow(new Exception("Exception!"));
for (int i=0; i<10; i++) {
if (i%2 == 0) {
stubber.doNothing();
} else {
stubber.doThrow(new Exception("Exception"));
}
}
stubber.when(myMockObject).someMethod(anyString());

The shortest would be
doReturn("Fail", "Success").when(myMock).doTheCall();

Related

If you want to use assertThrows while testing, should you do that with stubs or mocks?

I have this Method that throws an IllegalArgumentException when somebody tries to call it with value 0.
I want to write several stub and mock tests - for example - for the method getFrequentRenterPoints.
I coudn't figure out any "when" or "verify" statements which are used in mocks so I mixed parts of mocks and parts of stubs together and came up with this:
#Test
public void methodGetFrequentRenterPointsShouldThrowIllegalArgumentException() {
//given
Movie movieMock = mock(Movie.class);
//when
movieMock.getFrequentRenterPoints(0);
//then
assertThrows(IllegalArgumentException.class, () -> {
movieMock.getFrequentRenterPoints(0);
});
}
Is it okay to have in a class with other Mocks, or if I want to use assertThrows should I change this into a stub? Or can I use assertThrows with mocks?
The answer from Benjamin Eckardt is correct.
But I try to approach this question from another point of view: when to use mocking? This is one of my favourite answers to that question.
So in practise:
Say your code is like (just guessing all the business objects & names...):
List<RenterPoints> getFrequentRenterPoints(int renterId) {
if(p <= 0) {
throw new IllegalArgumentException();
}
// this is just the rest of code in which your test does not enter because
// of thrown exception
return somethingToReturn();
}
For this you do not need and you should not want to mock anything here.
But when things get more complicated like your method would be like:
List<RenterPoints> getFrequentRenterPoints(int renterId) {
if(p <= 0) {
throw new IllegalArgumentException();
}
// What is this?
// It is injected in the Movie - say - like
//
// #Resource
// private RenterPointService renterPointService;
List<RenterPoints> unfiltered = renterPointService.getRenterPoints(renterId);
return filterToFrequent(unfiltered);
}
Now if you test renterId >= 1 what about this renterPointService how do you instantiate it to not get NPE? Say if it is injected and requires to pull up heavy framework for testing or it requires very heavy construction or so? You do not, you mock it.
You are testing the class Movie not the class RenterPointService so you should not bother to think how RenterPointService works but what it returns when used in the class Movie. Still: you do not mock the class Movie which you are testing.
Assuming using you are using Mockito and using annotations the mocking would be then done in your test class like:
#Mock
private RenterPointService renterPointService;
#InjectMocks
private Movie movie;
Then you would do mocking of methods for renterPointService like:
when(renterPointService.getRenterPoints(anyInt))
.thenReturn(someListContaineingMockRenterPointsForThisTest);
Usually you expect the tested production method to throw and not the mock or stub. I drafted it by using new Movie().
Furthermore in that case it does not really make sense to separate the calls into when and then because if movieMock.getFrequentRenterPoints(0); throws, assertThrows(...) will never be executed.
To apply the given/when/then structure with the assertThrows API you could extract the passed lambda in some way, but I personally don't see much benefit in it.
#Test
public void methodGetFrequentRenterPointsShouldThrowIllegalArgumentException() {
// given
Movie movieMock = new Movie();
// when/then
assertThrows(IllegalArgumentException.class, () -> {
movieMock.getFrequentRenterPoints(0);
});
}

Check if-else statement in one time using JUnit testing

I try to test on how to get index 0 and 5 value from my file. I can get the value. But, to test the value with JUnit, i can only test if(index==0) but it did not check for (index==5).
So, how can i test both index in one time using if else ?
#Test
public void test(){
for(index = 0; index<arrayList.size(); index++){
if(index==0 && index==5){
given()
.header(something)
.get(something)
.then(something)
.body("try", contains(arrayList.get(index).getSomething(),arrayList.get(index).getSomething()))
.log().all()
.statusCode(HttpStatus.SC_OK)
}
}
}
In a unit test each test method verifies a single expectation about the tested units behavior.
Therefore you write different tests for different input and/or different expectations.
Also tests should not have (self written) logic.
If you need to iterate over input values you might consider Parameterized tests: http://blog.schauderhaft.de/2012/12/16/writing-parameterized-tests-with-junit-rules/
Simple:
for(index = 0; index<arrayList.size(); index++){
if(index==0 && index==5){
This says: if index is 0 and index is 5.
An int can't have two values at the same time. You probably want:
if(index==0 || index==5){
But of course: Timothy is correct, you want one "check" per test.
The proper solution would be: write a private helper method that takes an parameter indexToCheckFor, so that you can do
private void testForIndex(int indexToCheckFor) {
....
if(index == indexToCheckFor) {
and then have two #Test methods, one calling testForIndex(0), the other one calling for 5.

JUnit test cases for custom method

I'm studying for my first job interviews as Junior Java Developer and right now I'm trying to learn JUnit test cases. This is an example that I encountered and I must say it's really tricky for me (it's abstract code so I have no idea how to test it).
public class JuiceMaker {
public Juice makeJuice(final List<Fruit> fruits) throws RottenFruitException {
for (final Fruit fruit : fruits) {
if (FruitInspector.isFruitRotten(fruit)) {
throw new RottenFruitException(fruit.getName() + “ is rotten. Cannot make juice.”);
}
}
return Juicer.juice(fruits);
}
}
The only example I managed to create myself is this one:
JuiceMaker jm = new JuiceMaker();
#Test
public void isThrowingException() {
//when
try {
jm.throwsRuntime();
Assert.fail("Expected exception to be thrown");
} catch (RottenFruitException e) {
//then
assertThat(e)
.isInstanceOf(RottenFruitException.class)
.hasMessage((fruit.getName() + " is rotten. Cannot make juice.");
}
}
Any tips of what kind of tests I can perform on this piece of code? Thanks a lot for your help!
Welcome to JUnit, and good luck with your interviews!
First question to ask is what is the contract offered by this class? It takes a list of fruit, tests if any of the fruit are rotten, if so it throws an exception, otherwise it juices them. You can assume the "juice" method is tested elsewhere.
To me, that suggests these tests:
List with single good fruit
List with single rotten fruit
List with several good and one rotten fruit
Empty list
You could also test for null and invalid values, but that might be overdoing things just now.
Once you've decided what to test, then you can start thinking about implementing them. Looks like your implementation has a couple of errors, but you're heading in a good direction. You might find JUnit's "expected" parameter useful for testing for exceptions.
You seem to be instructing the JuiceMaker instance in your test to throw the exception to verify you can catch it.
You have to answer yourself whether that alone will exercise the loop iterating through the list of Fruit and the if() statement.
You can influence the JuiceMaker.makeJuice() better by passing different lists (null, empty, with no rotten fruit, with rotten fruit).
This way you are not forcing any exceptions but causing them - which exercises more paths through your code under test.
If you exercise the above scenarios, you should have a very decent test coverage of your method.
Hope this helps!
The two testcases you put up in your example-answer are going in the right direction, but only half way. Because both tests do not at all test your "class under test".
Reasonable tests would more look like:
public class JuiceMakerTest {
private JuiceMaker underTest;
#Before
public void setup() { underTest = new JuiceMaker; }
#Test(expected=RottenFruitException.class)
public void testThrowsOnRottenFruit() {
underTest.makeJuice(Collections.singletonList("rotten apple"));
}
#Test(expected=???)
public void testWithNullList() {
underTest.makeJuice(null);
}
#Test(expected=???)
public void testWithEmptyList() {
underTest.makeJuice(Collections.emptyList());
}
#Test
public void testXyz() {
Juice expectedResult = ...
assertThat(underTest.makeJuice(Collections.singletonList("apple")), is(expectedResult);
}
and so on. In other words: you follow the nice answer from hugh; and determine the possible ways to invoke your method. The ??? is just a place holder - indicating that you should think up what should happen here. Maybe you expect a specific exception; maybe the method returns a special empty juice ... all up to the contract of the method under test.
You derive error conditions from that, and expected results. And then you write at least one test for of the different aspects you collected.

Using a `when` as verification

I have a utility method used in hundreds of tests to mock the return value from a customised randomiser. Here's a (highly artificial) model of my code:
interface CardRandomiser{
Card getCard(Suit suit);
}
void mockCard(Suit suit, Face face) {
CardRandomiser rand = mock(CardRandomiser.class);
when(rand.getCard(suit)).thenReturn(new Card(suit, face));
Game.setCardRandomiser(rand);
}
This can then be used as:
mockCard(Suit.CLUBS, Face.QUEEN);
Card card = pickACardAnyCard();
assertThat(card.getFace(), is(Face.QUEEN));
However this makes some bugs a bit hard to pick up. If the method under test incorrectly asks for Suit.HEARTS then the mock returns null and the assertion correctly fails. But it's impossible to tell through the error message what was passed to the mock.
Clearly I could handle this with a verify. I could pass the mock back out of mockCard function and then separately verify that is was called with the correct value. But that really clutters up the tests assertions that are not really related to what's being tested. Given every time this method is called I am specifying an expected argument value I'd prefer to put the assertion in one place. Note that this all occurs before the method under test is called.
Ideally I'd like the when statement to throw an exception if it's called with an unexpected value. Something like:
when(rand.getCard(suit)).thenReturn(new Card(suit, face));
when(rand.getCard(intThat(not(is(suit))))).thenThrow(new IllegalArgumentException());
This works and stops the test when getCard is called which is better. But it still doesn't allow me to show what the incorrect argument was.
I also tried it using an ArgumentCaptor and then checking the captured value. But it's clear they are for verify statements rather than when statements.
Is there a standard Mockito way of doing this, or do I need to clutter my tests with verify statements?
You can configure mockito answer using thenAnswer, e.g.
private CardRandomiser mockCard(final Suit suit, final Face face) {
CardRandomiser rand = mock(CardRandomiser.class);
when(rand.getCard(any(Suit.class))).thenAnswer(new Answer<Card>() {
#Override
public Card answer(InvocationOnMock invocation) throws Throwable {
if(!suit.equals(invocation.getArguments()[0])) {
throw new IllegalArgumentException(
String.format("Value %s passed, but mocked for %s", invocation.getArguments()[0], suit));
}
return new Card(suit, face);
}
});
return rand;
}

writing a junit test case for the calling of a method

i am using eclemma and trying to increase my test coverage:
so far this is my code:
public RolesResponse findRolesByTenant(RolesRequest rolesRequest)
{
RolesResponse rolesResponse = new RolesResponse();
List<Role> roleList = null;
if (StringUtils.isNotBlank(rolesRequest.getTenantCode()))
{
roleList = roleFunctionService.getAllRolesAndFunctionsByTenant(rolesRequest.getTenantCode());
}
if (CollectionUtils.isNotEmpty(roleList))
{
rolesResponse.setRoles(roleList);
}
else
{
rolesResponse.setError(LayerContextHolder.getErrorObject());
}
return rolesResponse;
}
and here is my test:
#Test
public void findRolesByTenantTest()
{
RolesRequest rolesRequest = new RolesRequest();
rolesRequest.setTenantCode("test");
ErrorObject errorObject = new ErrorObject();
RolesResponse rolesResponse = rolesProcessService.findRolesByTenant(rolesRequest);
Assert.assertNull(rolesResponse.getError());
}
the only line eclemma is highlighting in red is this one:
rolesResponse.setError(LayerContextHolder.getErrorObject());
can someone help me in constructing the final test needed to cover this line
thanks
I'm really not a fan of your test anyway - what are you trying to prove by the error being null? That the list came back with something? Also, are you certain that your service will return the result you want in your test every single time?
Don't think of tests in terms of coverage; this will lead to brittle tests and tests that give a false sense of security. What you want to do is write tests that cover each condition that the code could encounter, and the line coverage can follow from that.
From your code, I see two cases.
roleFunctionService#getAllRolesByFunctionAndTenant can return a non-empty list.
It's implied that the resultant rolesResponse#roles contains whatever was in the list provided by the method, and this should be verified.
It's also implied that there is no error set on the object, so it should be null.
roleFunctionService#getAllRolesByFunctionAndTenant can return an empty list
Either the resultant rolesResponse#roles are empty or null; it'd be better if it were empty.
It's implied that there is an error on the object, which is specifically provided by LayerContextHolder.getErrorObject(). You should check to see that it's exactly that.
You'll get to the whole approach of writing this test through the use of a mocking framework.

Categories

Resources