Lindstorm
Lindstorm

Reputation: 889

Testing an abstract class with Mockito does not give the expected result

I have a class structure similar to the following

 public abstract class AbstractStep {
     private final Range RANGE;

     AbstractStep(AbstractStepBuilder builder) {
          RANGE = builder.range;   
     }


      public abstract static class AbstractStepBuilder {
           Range range;

           public AbstractStepBuilder setRange(int start, end end) {
                this.range = new Range(start, end);
                return self();
           }

           abstract AbstractStepBuilder self();
      }

      public static class Range() {
           private final int START;
           private final int END;

           private Range(int start, int end) {
                if(start < 0 || end < 0 || start >= end)
                      throw new IllegalArgumentException();
                START = start;
                END = end;
           }
      }
 }

I want to test setRange(int, int) in AbstractStepBuilder to see if the an IllegalArgumentException is thrown. I use TestNG and Mockito, and I have attempted the following using with the help of this.

 final class RangeTest {
      AbstractStepBuilder builder;

      @BeforeSuite 
      void setup() {
           builder = Mockito.mock(AbstractStepBuilder.class);
           Mockito.when(builder.self()).thenReturn(null);
       }

     @Test(expectedExceptions = IllegalArgumentException.class)
     final void testCreatingRangeWithNegativeStart() {
          builder.setRange(-1, 2);
     }
}

This test fails. I have also tried replacing Mockito.mock(AbstractStepBuilder.class) with Mockito.mock(AbstractStepBuilder.class, Mockito.CALLS_REAL_METHODS) as in the top answer of this question.

Note that if I make CodeRange as its own outer class, this test passes, so I do not believe it could be the test itself.

Why is this test failing, and is it possible to fix it without having to use a concrete class in the test instead?

Upvotes: 0

Views: 57

Answers (1)

daniu
daniu

Reputation: 14999

You're calling a method on a mock, that will never throw an Exception until you tell it to. You never mock a class you want to test.

If you want to test the actual class, you'll need to create a subclass of the step builder, create an instance and test that.

I think you can also create a spy (by Mockito.spy(AbstractStepBuilder.class)) to avoid creating a subclass just for the test.

Upvotes: 2

Related Questions