blob: 3838beef7a3b63f87b36fb0406f227374e064d4b [file] [log] [blame]
/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockitousage.strictness;
import org.assertj.core.api.ThrowableAssert;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.AdditionalAnswers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoSession;
import org.mockito.exceptions.misusing.PotentialStubbingProblem;
import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
import org.mockito.exceptions.verification.NoInteractionsWanted;
import org.mockito.quality.Strictness;
import org.mockitousage.IMethods;
import org.mockitoutil.TestBase;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
public class StrictnessPerStubbingTest {
MockitoSession mockito;
@Mock IMethods mock;
@Before
public void before() {
mockito = Mockito.mockitoSession().initMocks(this).strictness(Strictness.STRICT_STUBS).startMocking();
}
@Test
public void potential_stubbing_problem() {
//when
when(mock.simpleMethod("1")).thenReturn("1");
lenient().when(mock.differentMethod("2")).thenReturn("2");
//then on lenient stubbing, we can call it with different argument:
mock.differentMethod("200");
//but on strict stubbing, we cannot:
assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
@Override
public void call() throws Throwable {
mock.simpleMethod("100");
}
}).isInstanceOf(PotentialStubbingProblem.class);
}
@Test
public void doReturn_syntax() {
//when
lenient().doReturn("2").doReturn("3")
.when(mock).simpleMethod(1);
//then on lenient stubbing, we can call it with different argument:
mock.simpleMethod(200);
//and stubbing works, too:
assertEquals("2", mock.simpleMethod(1));
assertEquals("3", mock.simpleMethod(1));
}
@Test
public void doReturn_varargs_syntax() {
//when
lenient().doReturn("2", "3")
.when(mock).simpleMethod(1);
//then on lenient stubbing, we can call it with different argument with no exception:
mock.simpleMethod(200);
//and stubbing works, too:
assertEquals("2", mock.simpleMethod(1));
assertEquals("3", mock.simpleMethod(1));
}
@Test
public void doThrow_syntax() {
//when
lenient()
.doThrow(IllegalArgumentException.class)
.doThrow(IllegalStateException.class)
.when(mock).simpleMethod(1);
//then on lenient stubbing, we can call it with different argument with no exception:
mock.simpleMethod(200);
//and stubbing works, too:
assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
public void call() throws Throwable {
mock.simpleMethod(1);
}
}).isInstanceOf(IllegalArgumentException.class);
//testing consecutive call:
assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
public void call() throws Throwable {
mock.simpleMethod(1);
}
}).isInstanceOf(IllegalStateException.class);
}
@Test
public void doThrow_vararg_syntax() {
//when
lenient()
.doThrow(IllegalArgumentException.class, IllegalStateException.class)
.when(mock).simpleMethod(1);
//then on lenient stubbing, we can call it with different argument with no exception:
mock.simpleMethod(200);
//and stubbing works, too:
assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
public void call() throws Throwable {
mock.simpleMethod(1);
}
}).isInstanceOf(IllegalArgumentException.class);
//testing consecutive call:
assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
public void call() throws Throwable {
mock.simpleMethod(1);
}
}).isInstanceOf(IllegalStateException.class);
}
@Test
public void doThrow_instance_vararg_syntax() {
//when
lenient()
.doThrow(new IllegalArgumentException(), new IllegalStateException())
.when(mock).simpleMethod(1);
//then on lenient stubbing, we can call it with different argument with no exception:
mock.simpleMethod(200);
//and stubbing works, too:
assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
public void call() throws Throwable {
mock.simpleMethod(1);
}
}).isInstanceOf(IllegalArgumentException.class);
//testing consecutive call:
assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
public void call() throws Throwable {
mock.simpleMethod(1);
}
}).isInstanceOf(IllegalStateException.class);
}
static class Counter {
int increment(int x) {
return x + 1;
}
void scream(String message) {
throw new RuntimeException(message);
}
}
@Test
public void doCallRealMethod_syntax() {
//when
Counter mock = mock(Counter.class);
lenient().doCallRealMethod().when(mock).increment(1);
//then no exception and default return value if we call it with different arg:
assertEquals(0, mock.increment(0));
//and real method is called when using correct arg:
assertEquals(2, mock.increment(1));
}
@Test
public void doNothing_syntax() {
//when
final Counter spy = spy(Counter.class);
lenient().doNothing().when(spy).scream("1");
//then no stubbing exception and real method is called if we call stubbed method with different arg:
assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
@Override
public void call() throws Throwable {
spy.scream("2");
}
}).hasMessage("2");
//and we do nothing when stubbing called with correct arg:
spy.scream("1");
}
@Test
public void doAnswer_syntax() {
//when
lenient().doAnswer(AdditionalAnswers.returnsFirstArg()).when(mock).simpleMethod("1");
//then on lenient stubbing, we can call it with different argument:
mock.simpleMethod("200");
//and stubbing works, too:
assertEquals("1", mock.simpleMethod("1"));
}
@Test
public void unnecessary_stubbing() {
//when
when(mock.simpleMethod("1")).thenReturn("1");
lenient().when(mock.differentMethod("2")).thenReturn("2");
//then unnecessary stubbing flags method only on the strict stubbing:
assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
@Override
public void call() throws Throwable {
mockito.finishMocking();
}
}).isInstanceOf(UnnecessaryStubbingException.class)
.hasMessageContaining("1. -> ")
//good enough to prove that we're flagging just one unnecessary stubbing:
//TODO 792: this assertion is duplicated with StrictnessPerMockTest
.isNot(TestBase.hasMessageContaining("2. ->"));
}
@Test
public void unnecessary_stubbing_with_doReturn() {
//when
lenient().doReturn("2").when(mock).differentMethod("2");
//then no exception is thrown:
mockito.finishMocking();
}
@Test
public void verify_no_more_invocations() {
//when
when(mock.simpleMethod("1")).thenReturn("1");
lenient().when(mock.differentMethod("2")).thenReturn("2");
//and:
mock.simpleMethod("1");
mock.differentMethod("200"); // <- different arg
//then 'verifyNoMoreInteractions' flags the lenient stubbing (called with different arg)
//and reports it with [?] in the exception message
assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
@Override
public void call() throws Throwable {
verifyNoMoreInteractions(mock);
}
}).isInstanceOf(NoInteractionsWanted.class)
.hasMessageContaining("1. ->")
.hasMessageContaining("2. [?]->");
//TODO 792: assertion duplicated with StrictnessPerMockTest
// and we should use assertions based on content of the exception rather than the string
}
@After
public void after() {
mockito.finishMocking();
}
}