blob: 2e720332383d5c769b53f814b8c25fd526a142d0 [file] [log] [blame]
/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito.internal.verification.checkers;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import java.util.List;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.exceptions.verification.VerificationInOrderFailure;
import org.mockito.internal.invocation.InvocationBuilder;
import org.mockito.internal.invocation.InvocationMatcher;
import org.mockito.internal.verification.InOrderContextImpl;
import org.mockito.internal.verification.api.InOrderContext;
import org.mockito.invocation.Invocation;
import org.mockitousage.IMethods;
public class NumberOfInvocationsInOrderCheckerTest {
private InvocationMatcher wanted;
private List<Invocation> invocations;
private InOrderContext context;
private IMethods mock;
@Rule
public ExpectedException exception = ExpectedException.none();
@Before
public void setup() {
context = new InOrderContextImpl();
mock = mock(IMethods.class, "mock");
}
@Test
public void shouldPassIfWantedIsZeroAndMatchingChunkIsEmpty() {
wanted = buildSimpleMethod().toInvocationMatcher();
invocations = emptyList();
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 0, context);
}
@Test
public void shouldPassIfChunkMatches() throws Exception {
wanted = buildSimpleMethod().toInvocationMatcher();
invocations = asList(buildSimpleMethod().toInvocation());
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 1, context);
}
@Test
public void shouldReportTooLittleInvocations() throws Exception {
Invocation first = buildSimpleMethod().toInvocation();
Invocation second = buildSimpleMethod().toInvocation();
wanted = buildSimpleMethod().toInvocationMatcher();
invocations = asList(first, second);
exception.expect(VerificationInOrderFailure.class);
exception.expectMessage("mock.simpleMethod()");
exception.expectMessage("Wanted 4 times");
exception.expectMessage("But was 2 times");
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 4, context);
}
@Test
public void shouldMarkAsVerifiedInOrder() throws Exception {
Invocation invocation = buildSimpleMethod().toInvocation();
invocations = asList(invocation);
wanted = buildSimpleMethod().toInvocationMatcher();
assertThat(context.isVerified(invocation)).isFalse();
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 1, context);
assertThat(context.isVerified(invocation)).isTrue();
}
@Test
public void shouldReportTooLittleActual() throws Exception {
wanted = buildSimpleMethod().toInvocationMatcher();
invocations = asList(buildSimpleMethod().toInvocation(), buildSimpleMethod().toInvocation());
exception.expect(VerificationInOrderFailure.class);
exception.expectMessage("mock.simpleMethod()");
exception.expectMessage("Wanted 100 times");
exception.expectMessage("But was 2 times");
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100, context);
}
@Test
public void shouldReportWithLastInvocationStackTrace() throws Exception {
wanted = buildSimpleMethod().toInvocationMatcher();
invocations = asList(buildSimpleMethod().toInvocation(), buildSimpleMethod().toInvocation());
exception.expect(VerificationInOrderFailure.class);
exception.expectMessage("mock.simpleMethod()");
exception.expectMessage("Wanted 100 times");
exception.expectMessage("But was 2 times");
exception.expectMessage(containsTimes("-> at", 2));
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100, context);
}
@Test
public void shouldNotReportWithLastInvocationStackTraceIfNoInvocationsFound() throws Exception {
invocations = emptyList();
wanted = buildSimpleMethod().toInvocationMatcher();
exception.expect(VerificationInOrderFailure.class);
exception.expectMessage("mock.simpleMethod()");
exception.expectMessage("Wanted 100 times");
exception.expectMessage("But was 0 times");
exception.expectMessage(containsTimes("-> at", 1));
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100, context);
}
@Test
public void shouldReportWithFirstUndesiredInvocationStackTrace() throws Exception {
Invocation first = buildSimpleMethod().toInvocation();
Invocation second = buildSimpleMethod().toInvocation();
Invocation third = buildSimpleMethod().toInvocation();
invocations = asList(first, second, third);
wanted = buildSimpleMethod().toInvocationMatcher();
exception.expect(VerificationInOrderFailure.class);
exception.expectMessage("" + third.getLocation());
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 2, context);
}
@Test
public void shouldReportTooManyActual() throws Exception {
Invocation first = buildSimpleMethod().toInvocation();
Invocation second = buildSimpleMethod().toInvocation();
invocations = asList(first, second);
wanted = buildSimpleMethod().toInvocationMatcher();
exception.expectMessage("Wanted 1 time");
exception.expectMessage("But was 2 times");
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 1, context);
}
@Test
public void shouldReportNeverWantedButInvoked() throws Exception {
Invocation first = buildSimpleMethod().toInvocation();
invocations = asList(first);
wanted = buildSimpleMethod().toInvocationMatcher();
exception.expect(VerificationInOrderFailure.class);
exception.expectMessage("mock.simpleMethod()");
exception.expectMessage("Wanted 0 times");
exception.expectMessage("But was 1 time. Undesired invocation");
exception.expectMessage("" + first.getLocation());
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 0, context);
}
@Test
public void shouldMarkInvocationsAsVerified() throws Exception {
Invocation invocation = buildSimpleMethod().toInvocation();
assertThat(invocation.isVerified()).isFalse();
invocations = asList(invocation);
wanted = buildSimpleMethod().toInvocationMatcher();
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 1, context);
assertThat(invocation.isVerified()).isTrue();
}
private static BaseMatcher<String> containsTimes(String value, int amount) {
return new StringContainsNumberMatcher(value, amount);
}
private static class StringContainsNumberMatcher extends TypeSafeMatcher<String> {
private final String expected;
private final int amount;
StringContainsNumberMatcher(String expected, int amount) {
this.expected = expected;
this.amount = amount;
}
@Override
public boolean matchesSafely(String text) {
int lastIndex = 0;
int count = 0;
while (lastIndex != -1) {
lastIndex = text.indexOf(expected, lastIndex);
if (lastIndex != -1) {
count++;
lastIndex += expected.length();
}
}
return count == amount;
}
@Override
public void describeTo(Description description) {
description.appendText("containing '" + expected + "' exactly " + amount + " times");
}
}
private InvocationBuilder buildSimpleMethod() {
return new InvocationBuilder().mock(mock).simpleMethod();
}
}