Reputation: 889
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
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