JUnit tests for custom method

I am studying my first interviews as a junior Java developer and I am currently trying to learn JUnit test cases. This is an example I came across and I have to say that it is very difficult for me (this is abstract code, so I don’t know 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 have managed to create is the following:

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 on what tests I can run on this piece of code? Many thanks for your help!

+3


source to share


3 answers


Welcome to JUnit, and good luck with your interviews!

The first question asked is is the contract offered by this class? It takes a list of fruits, tests if any of the fruits are rotten, if it raises an exception, otherwise it will sap them. You might assume that the "juice" method has been tested elsewhere.

For me this assumes the following tests:



  • List with one good fruit
  • List with one rotten fruit
  • A list with several good and one rotten fruit.
  • Empty list

You can also check for null and invalid values, but this can be overdone now.

Once you decide what to test, you can start thinking about implementing them. It looks like your implementation has a few bugs, but you're heading in a good direction. You may find the JUnit Expected parameter useful for testing exceptions.

+3


source


You seem to be instructing the instance JuiceMaker

in your test to throw an exception in order to check if you can catch it.

You have to answer yourself if this will loop through the list Fruit

and operator if()

.

You can better influence by JuiceMaker.makeJuice()

passing different lists ( null

, empty, no rotten fruit, with rotten fruit).



This way, you are not throwing any exceptions, but rather throwing them - which take more paths through your code under test.

If you are using the above scenarios you should have very decent test coverage for your method.

Hope this helps!

+2


source


The two test files you put in your example answer go in the right direction, but only halfway . Since both tests do not at all check your "class under test".

Reasonable tests will look bigger:

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);
  }

      

etc. In other words: you follow a good answer from hugh; and identify possible ways to call your method. ???

is simply the owner of the place, which indicates that you have to think of what should happen here. You may be expecting a specific exception; maybe the method returns a special empty juice ... everything up to the contract of the method being tested.

You get error conditions from this and the expected results. And then you write at least one test for the different aspects that you have collected.

+2


source







All Articles