Showing posts with label JUNIT. Show all posts
Showing posts with label JUNIT. Show all posts

Wednesday, January 17, 2018

Implementing mocking with JUNITs

JUNITs are an easy and effective way to unit test your code. However when writing a JUNIT you need to ensure that the scope of test case remains within that class
only and does not go beyond it.
What this means is that say you have a class A which call a method of Class B from within it. Then ur unit test case should be limited to methods of Class A and
should not test method of Class B otherwise the test case will become an integration test. This can be achieved using a Mock framework such as Mockito and this is
where JUNITs become tricky as well.

I was trying to write JUNITs using Mockito for a simple case as mentioned above. Class code below:

Class to be tested:

public Class A {
  public String parseEvent(String line) {
// some business logic
ClassB bObj = new ClassB();
String randomNum = bObj.getRandomNum().toString();
return line.append(randomNum);
  }
}

Junit:

public class ATest {

   @Test
   public void testParseEvent() {
       String inputLine= <some data>;
       String expectedOutput =<some data>;
       
       ClassB bObject = mock(ClassB.class);
       when(bOject.getRandomNum()).thenReturn(2);
       
       Class A aObject = new ClassA();
       String result = aObject.parseEvent(inputLine);
       Assert.assertArrayEquals(expectedOutput.getBytes(),result.getBytes());
       
   }

}

This looked alright to me. I was trying to mock class B's method so as to return a predetermined number and then compare expected and actual output.
However despite trying above and many other approaches I could see that B's method was actually getting called instead of getting mocked.

After a lot of googling found out that the issue was not with Junit or Mocking but with the way Class A was written. Since it was instantiating object of Class B, 
the mock object got lost and acutal instance got called. After refactoring Class A, Junit worked fine. Refactored code below:

public ClassA {

   private ClassB obj=null;

   public ClassA(ClassB obj) {
this.obj=obj;
   }

  public String parseEvent(String line) {
// some business logic
String randomNum = obj.getRandomNum().toString();
return line.append(randomNum);
  }
}

After refactoring Class A's code, in my JUNIT i passed the mocked object of Class B when creating object of Class A. The mocking worked fine and Junit returned 
expected result. 
Happy Ending :)