doReturn() method of Mockito is not returning desired value in code

Sagar Kansara :

I am trying to unit test following method:

Class TestClass {

    public List<String> test(String a, String b, String c, String d) throws IOException {
      MyClass myClass = new MyClass();
      myClass.setFileName(functionName);
      int outputNum = myClass.getOutputTableArgsSize();
      List<String> list = new ArrayList<String> ();



      ... and some more code based on outputNum value.

      return list;
    }
}

My unit test method looks like below:

    @Test
    public void testMyTestClass() throws Exception {
        TestClass myClass = new TestClass();
        MyClass myClass = mock(MyClass.class);
        doNothing().when(myClass).setFileName(anyString());
        doReturn(11).when(myClass).getOutputTableArgsSize();

        .... Some more lines and based on return value 11, I am expecting the size of the list to be return is 1. 

        assertEquals(TestClass.test("ab", "cd", "ef", "gh").size(), 1);
    }

I am trying to return 11 at line doReturn(11).when(myClass).getOutputTableArgsSize(); but when I am checking the return value is always 0.

What is wrong in the above unit test and why I am always getting 0 insted of value mentioned in doReturn()?

Nkosi :

The mock in the test

 MyClass myClass = mock(MyClass.class);

is not the instance used in the method under test, since the method under test creates its own instance.

public List<String> test(String a, String b, String c, String d) throws IOException {
    MyClass myClass = new MyClass();
    //...

The method under test is tightly coupled to an implementation concern that makes testing it in isolation difficult.

Consider refactoring the subject class under test to explicitly depend on that class via constructor injection.

If how ever a new instance is required per call then consider using a factory

public interface MyClassFactory {
    public MyClass Create(string functionName);
}

public class MyClassFactoryImp implements MyClassFactory {
    public MyClass Create(string functionName) {
        MyClass myClass = new MyClass();
        myClass.setFileName(functionName);
        return myClass
    }
}

and refactoring the subject class accordingly

class TestClass {
    MyClassFactory factory;
    public TestClass(MyClassFactory factory) {
        this.factory = factory;
    }

    public List<String> test(String a, String b, String c, String d) throws IOException {
      MyClass myClass = factory.Create(functionName);
      int outputNum = myClass.getOutputTableArgsSize();
      List<String> list = new ArrayList<String> ();

      //... and some more code based on outputNum value.

      return list;
    }
}

So that a proper isolated test can be constructed and exercised

@Test
public void testMyTestClass() throws Exception {
    //Arrange
    MyClass myClass = mock(MyClass.class);
    doNothing().when(myClass).setFileName(anyString());
    doReturn(11).when(myClass).getOutputTableArgsSize();

    MyClassFactory factory = mock(MyClassFactory.class);
    doReturn(myClass).when(factory).Create(anyString());

    TestClass subject = new TestClass(factory);

    //Act
    List<String> result = subject.test("ab", "cd", "ef", "gh");

    //Assert
    assertEquals(result.size(), 1);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=153566&siteId=1