Home | History | Annotate | Download | only in checkers
      1 /*
      2  * Copyright (c) 2007 Mockito contributors
      3  * This program is made available under the terms of the MIT License.
      4  */
      5 
      6 package org.mockito.internal.verification.checkers;
      7 
      8 import static java.util.Arrays.asList;
      9 import static java.util.Collections.emptyList;
     10 import static org.assertj.core.api.Assertions.assertThat;
     11 
     12 import java.util.List;
     13 import org.hamcrest.BaseMatcher;
     14 import org.hamcrest.Description;
     15 import org.hamcrest.TypeSafeMatcher;
     16 import org.junit.Rule;
     17 import org.junit.Test;
     18 import org.junit.rules.ExpectedException;
     19 import org.junit.rules.TestName;
     20 import org.junit.runner.RunWith;
     21 import org.mockito.Mock;
     22 import org.mockito.exceptions.verification.NeverWantedButInvoked;
     23 import org.mockito.exceptions.verification.TooLittleActualInvocations;
     24 import org.mockito.exceptions.verification.TooManyActualInvocations;
     25 import org.mockito.internal.invocation.InvocationBuilder;
     26 import org.mockito.internal.invocation.InvocationMatcher;
     27 import org.mockito.invocation.Invocation;
     28 import org.mockito.junit.MockitoJUnitRunner;
     29 import org.mockitousage.IMethods;
     30 
     31 @RunWith(MockitoJUnitRunner.class)
     32 public class NumberOfInvocationsCheckerTest {
     33 
     34     private InvocationMatcher wanted;
     35 
     36     private List<Invocation> invocations;
     37 
     38     @Mock
     39     private IMethods mock;
     40 
     41     @Rule
     42     public ExpectedException exception = ExpectedException.none();
     43 
     44     @Rule
     45     public TestName testName = new TestName();
     46 
     47     @Test
     48     public void shouldReportTooLittleActual() throws Exception {
     49         wanted = buildSimpleMethod().toInvocationMatcher();
     50         invocations = asList(buildSimpleMethod().toInvocation(), buildSimpleMethod().toInvocation());
     51 
     52         exception.expect(TooLittleActualInvocations.class);
     53         exception.expectMessage("mock.simpleMethod()");
     54         exception.expectMessage("Wanted 100 times");
     55         exception.expectMessage("But was 2 times");
     56 
     57         NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100);
     58     }
     59 
     60     @Test
     61     public void shouldReportWithLastInvocationStackTrace() throws Exception {
     62         wanted = buildSimpleMethod().toInvocationMatcher();
     63         invocations = asList(buildSimpleMethod().toInvocation(), buildSimpleMethod().toInvocation());
     64 
     65         exception.expect(TooLittleActualInvocations.class);
     66         exception.expectMessage("mock.simpleMethod()");
     67         exception.expectMessage("Wanted 100 times");
     68         exception.expectMessage("But was 2 times");
     69         exception.expectMessage(containsTimes("-> at", 2));
     70 
     71         NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100);
     72     }
     73 
     74     @Test
     75     public void shouldNotReportWithLastInvocationStackTraceIfNoInvocationsFound() throws Exception {
     76         invocations = emptyList();
     77         wanted = buildSimpleMethod().toInvocationMatcher();
     78 
     79         exception.expect(TooLittleActualInvocations.class);
     80         exception.expectMessage("mock.simpleMethod()");
     81         exception.expectMessage("Wanted 100 times");
     82         exception.expectMessage("But was 0 times");
     83         exception.expectMessage(containsTimes("-> at", 1));
     84 
     85         NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 100);
     86     }
     87 
     88     @Test
     89     public void shouldReportWithFirstUndesiredInvocationStackTrace() throws Exception {
     90         Invocation first = buildSimpleMethod().toInvocation();
     91         Invocation second = buildSimpleMethod().toInvocation();
     92         Invocation third = buildSimpleMethod().toInvocation();
     93 
     94         invocations = asList(first, second, third);
     95         wanted = buildSimpleMethod().toInvocationMatcher();
     96 
     97         exception.expect(TooManyActualInvocations.class);
     98         exception.expectMessage("" + third.getLocation());
     99         NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 2);
    100     }
    101 
    102     @Test
    103     public void shouldReportTooManyActual() throws Exception {
    104         Invocation first = buildSimpleMethod().toInvocation();
    105         Invocation second = buildSimpleMethod().toInvocation();
    106 
    107         invocations = asList(first, second);
    108         wanted = buildSimpleMethod().toInvocationMatcher();
    109 
    110         exception.expectMessage("Wanted 1 time");
    111         exception.expectMessage("But was 2 times");
    112 
    113         NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 1);
    114     }
    115 
    116     @Test
    117     public void shouldReportNeverWantedButInvoked() throws Exception {
    118         Invocation first = buildSimpleMethod().toInvocation();
    119 
    120         invocations = asList(first);
    121         wanted = buildSimpleMethod().toInvocationMatcher();
    122 
    123         exception.expect(NeverWantedButInvoked.class);
    124         exception.expectMessage("Never wanted here");
    125         exception.expectMessage("But invoked here");
    126         exception.expectMessage("" + first.getLocation());
    127 
    128         NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 0);
    129     }
    130 
    131 	@Test
    132 	public void shouldMarkInvocationsAsVerified() throws Exception {
    133 		Invocation invocation = buildSimpleMethod().toInvocation();
    134 		assertThat(invocation.isVerified()).isFalse();
    135 
    136 		invocations = asList(invocation);
    137 		wanted = buildSimpleMethod().toInvocationMatcher();
    138 		NumberOfInvocationsChecker.checkNumberOfInvocations(invocations, wanted, 1);
    139 		assertThat(invocation.isVerified()).isTrue();
    140 	}
    141 
    142     private InvocationBuilder buildSimpleMethod() {
    143         return new InvocationBuilder().mock(mock).simpleMethod();
    144     }
    145 
    146     private static BaseMatcher<String> containsTimes(String value, int amount) {
    147         return new StringContainsNumberMatcher(value, amount);
    148     }
    149 
    150     private static class StringContainsNumberMatcher extends TypeSafeMatcher<String> {
    151 
    152         private final String expected;
    153 
    154         private final int amount;
    155 
    156         StringContainsNumberMatcher(String expected, int amount) {
    157             this.expected = expected;
    158             this.amount = amount;
    159         }
    160 
    161         public boolean matchesSafely(String text) {
    162             int lastIndex = 0;
    163             int count = 0;
    164             while (lastIndex != -1) {
    165                 lastIndex = text.indexOf(expected, lastIndex);
    166                 if (lastIndex != -1) {
    167                     count++;
    168                     lastIndex += expected.length();
    169                 }
    170             }
    171             return count == amount;
    172         }
    173 
    174         public void describeTo(Description description) {
    175             description.appendText("containing '" + expected + "' exactly " + amount + " times");
    176         }
    177 
    178     }
    179 }
    180