Search code examples
javaunit-testingjunitmockito

Mockito stubbed method not being called


I'm new to Mockito and have been having trouble with stubbing. I wanted to test a method but stub one line of that method which is a call to another class's method. Based on the code below, I was expecting Optional.empty() but got Optional.of("str should not be null"). What am I doing wrong?

public class ClassA {
    public String str;

    public Optional<String> method1() {
        if (str == null) { 
            return Optional.of("str should not be null"); 
        }
        return Optional.empty();
    }
}
        
public class ClassB {
    public String thing;
    public Optional<String> method2() {
        ClassA classA = new ClassA();
        Optional<String> str2 = classA.method1();
        if (str2.isPresent()) return str2;
        if (thing == null) return Optional.of("thing should not be null");
        return Optional.empty();
    }
}

public class ClassBTest {
    @Test
    public void method1_test() {
        ClassB classBSpy = spy(new ClassB());
        ClassA classASpy = spy(new ClassA());
        doReturn(Optional.empty()).when(classASpy).method1();

        assertEquals(Optional.empty(), classBSpy.method2());
    }
}
        

Solution

  • To make a stub of ClassA effective in ClaasB, you need a way to insert the Spy/Mock of CLassA into CLassB, i.e. through the constructor:

    public class ClassB {
        public String thing;
    
        private ClassA classA = new ClassA();
    
        public ClassB() {
            super();
        }
    
    
        public ClassB(ClassA classA) {
            super();
            this.classA = classA;
        }
    
        public Optional<String> method2() {
            Optional<String> str2 = classA.method1();
            if (str2.isPresent()) return str2;
            if (thing == null) return Optional.of("thing should not be null");
            return Optional.empty();
        }
    }
     
    
    public class ClassBTest {
        @Test
        public void method1_test() {
            ClassA classASpy = spy(new ClassA());
            ClassB classB = new ClassB(classASpy);
            doReturn(Optional.empty()).when(classASpy).method1();
    
            assertEquals(Optional.empty(), classB.method2());
        }
    }
    

    But the test still fails since Optional.empty().isPresent() is false and thing is awlays null.