vendredi 5 juin 2015

How to write unit test by mocking, when you have zero arg:constructors

I was trying to write unit test using jmocks and junit. (My Project uses core java- no frameworks-) I could not write unit test for some of my classes, by mocking external dependencies, when dependencies were initialized in a a no arg-constructor.

As i cannot provide the actual code, trying to explain the scenario by an example

public interface Apple {

String variety();

}

Implementation.

public class MalgovaApple implements Apple {

  @Override
  public String variety() {
         return "Malgova";

  }

}

Class to be tested

public class VarietyChecker {
private Apple apple;

VarietyChecker(){
this.apple = new MalgovaApple();
// instead of new, a factory method is used in actual application
}

public String printAppleVariety(){
    String variety = apple.variety();
    if(variety.length() < 3){
       System.out.println("Donot use Code names- Use complete names");
       return "bad";
        }
       return "good";
}
}

Junit test using jmock

public class VarietyCheckerUnitTest{
Mockery context = new JUnit4Mockery();
@Before
public void setUp() throws Exception {
}

@After
public void tearDown() throws Exception {
}

@Test
public void test_VarietyChecker() throws Exception{

    final Apple mockapple = context.mock(Apple.class);

    VarietyChecker printer = new VarietyChecker();
    context.checking(new Expectations(){{
        oneOf(mockapple).variety();will(returnValue("as"));
    }});
    String varietyNameValid = printer.printAppleVariety();

    assertEquals("bad",varietyNameValid);


} }

This test fails - Mocking does not work the values "as" is not injected, the test class executes with MalgovaApple ...

Now if we add below constructor to VarietyChecker and use it test case - it gives expected output...

public VarietyChecker(Apple apple) {
    super();
    this.apple = apple;
}

and in unit test create test class object like VarietyChecker printer = new VarietyChecker(mockapple);

Exposing a new constructor just for the purpose of testing is not a good idea. After all it is said that you should not alter the code for testing alone, more than that, i am afraid we have already written "some"(amount) code...

Am i missing something in junit or jmock that can make mocking work even incase of no-arg constructors. Or is this a limitation of simple junit and jmocks and should i migrate to something powerful like Jmockit /PowerMock

Aucun commentaire:

Enregistrer un commentaire