0

I'm currently working on some unit tests for my application using JUnit and EasyMock for mocking complex objects, and I'm facing a dilemma. For instance, I'm testing each function with the following test template:

public static int foo(Object a){
// my function that needs to be tested

  int quantity = 0;
  if(a != null && a.getInt() != null ){
    quantity = a.getInt();
  }
  return quantity;

}

public void testFoo(){
// my unit test for the function foo
  int expectedValue = 0;
  int output = 0;

//Setting up my mocks
  Object a_mock = EasyMock.create(Object.class)
  EasyMock.expect(a_mock.getInt()).andReturn(null).times(1);
  EasyMock.expect(a_mock.getInt()).andReturn(1).times(2);

//Executing
  // Case 1: a is null
  expectedValue = 0;
  output = foo(null);
  assertEquals(expectedValue, output);

  // Case 2: a.getIn() is null
  expectedValue = 0;
  output = foo(a_mock);
  assertEquals(expectedValue, output);

  //Case 3: nominal case
  expectedValue = 1;
  output = foo(a_mock);
  assertEquals(expectedValue, output);

}

This structure works pretty well, but here is my point: unit testing is a testing process that allows you to validate if each unit (here a function) gives you the wanted output, knowing the input. This means that if I need to modify my function foo, but without modifying what it does, my unit tests still have to pass. Theoretically, if foo is changed like this:

public static int foo(Object a){

  int quantity = 0;
  if(a != null && a.getInt() != null && a.getInt() != 5){ //modification here
    quantity = a.getInt();
  }
  return quantity;

}

Then testFoo still has to pass. But it doesn't, because the .times(2) must be changed in .times(3).

So here is my question : is the .times(x) method of EasyMock an issue for the robustness of unit tests ? And if no, then what is the minimal level of robustness a unit test must have ?

MatthiasDec
  • 145
  • 1
  • 11
  • Could you possibly avoid mocking the methods at all? See https://stackoverflow.com/questions/60139201/performing-non-mock-state-based-unit-testing-of-non-trivial-functions-and-their/60196328#60196328 – Dirk Herrmann Mar 16 '20 at 23:59

1 Answers1

0

First, as mentinoned in the comment, you may not need to pass a mock for a at all. Maybe using some real instances of Object is simple enough and does not have any negative consequences on your tests.

Second, if you come to the conclusion that mocking is necessary, then you can avoid using times by providing individual mocks for each of the tests. You only have to call times because you are re-using a_mock between different tests.

Going one step further, you should even consider splitting up your function testFoo into three different functions - or directly convert testFoo into a parameterized test with three parameter sets.

Dirk Herrmann
  • 5,550
  • 1
  • 21
  • 47