blob: af9d3cb801e4f0fa06d6a7a96084bf4c360f285d [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 java.util.List;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.exceptions.verification.NeverWantedButInvoked;
import org.mockito.exceptions.verification.TooLittleActualInvocations;
import org.mockito.exceptions.verification.TooManyActualInvocations;
import org.mockito.internal.invocation.InvocationBuilder;
import org.mockito.internal.invocation.InvocationMatcher;
import org.mockito.invocation.Invocation;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockitousage.IMethods;
@RunWith(MockitoJUnitRunner.class)
public class NumberOfInvocationsCheckerTest {
private InvocationMatcher wanted;
private List<Invocation> invocations;
@Mock
private IMethods mock;
@Rule
public ExpectedException exception = ExpectedException.none();
@Rule
public TestName testName = new TestName();
@Test
public void shouldReportTooLittleActual() throws Exception {
wanted = buildSimpleMethod().toInvocationMatcher();
invocations = asList(buildSimpleMethod().toInvocation(), buildSimpleMethod().toInvocation());
exception.expect(TooLittleActualInvocations.class);
exception.expectMessage("mock.simpleMethod()");
exception.expectMessage("Wanted 100 times");
exception.expectMessage("But was 2 times");
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100);
}
@Test
public void shouldReportWithLastInvocationStackTrace() throws Exception {
wanted = buildSimpleMethod().toInvocationMatcher();
invocations = asList(buildSimpleMethod().toInvocation(), buildSimpleMethod().toInvocation());
exception.expect(TooLittleActualInvocations.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);
}
@Test
public void shouldNotReportWithLastInvocationStackTraceIfNoInvocationsFound() throws Exception {
invocations = emptyList();
wanted = buildSimpleMethod().toInvocationMatcher();
exception.expect(TooLittleActualInvocations.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);
}
@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(TooManyActualInvocations.class);
exception.expectMessage("" + third.getLocation());
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 2);
}
@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);
}
@Test
public void shouldReportNeverWantedButInvoked() throws Exception {
Invocation first = buildSimpleMethod().toInvocation();
invocations = asList(first);
wanted = buildSimpleMethod().toInvocationMatcher();
exception.expect(NeverWantedButInvoked.class);
exception.expectMessage("Never wanted here");
exception.expectMessage("But invoked here");
exception.expectMessage("" + first.getLocation());
NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 0);
}
@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);
assertThat(invocation.isVerified()).isTrue();
}
private InvocationBuilder buildSimpleMethod() {
return new InvocationBuilder().mock(mock).simpleMethod();
}
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;
}
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;
}
public void describeTo(Description description) {
description.appendText("containing '" + expected + "' exactly " + amount + " times");
}
}
}