Home | History | Annotate | Download | only in debugging
      1 /*
      2  * Copyright (c) 2007 Mockito contributors
      3  * This program is made available under the terms of the MIT License.
      4  */
      5 package org.mockitousage.debugging;
      6 
      7 import org.assertj.core.api.Condition;
      8 import org.junit.Test;
      9 import org.mockito.InOrder;
     10 import org.mockito.invocation.DescribedInvocation;
     11 import org.mockito.listeners.InvocationListener;
     12 import org.mockito.listeners.MethodInvocationReport;
     13 
     14 import java.util.ArrayList;
     15 import java.util.List;
     16 
     17 import static org.assertj.core.api.Assertions.assertThat;
     18 import static org.junit.Assert.fail;
     19 import static org.mockito.BDDMockito.given;
     20 import static org.mockito.BDDMockito.willReturn;
     21 import static org.mockito.Mockito.any;
     22 import static org.mockito.Mockito.doThrow;
     23 import static org.mockito.Mockito.inOrder;
     24 import static org.mockito.Mockito.mock;
     25 import static org.mockito.Mockito.withSettings;
     26 
     27 
     28 /**
     29  * Ensures that custom listeners can be registered and will be called every time
     30  * a method on a mock is invoked.
     31  */
     32 public class InvocationListenerCallbackTest {
     33 
     34     @Test
     35     public void should_call_single_listener_when_mock_return_normally() throws Exception {
     36         // given
     37         RememberingListener listener = new RememberingListener();
     38         Foo foo = mock(Foo.class, withSettings().invocationListeners(listener));
     39         willReturn("basil").given(foo).giveMeSomeString("herb");
     40 
     41         // when
     42         foo.giveMeSomeString("herb");
     43 
     44         // then
     45         assertThat(listener).is(notifiedFor("basil", getClass().getSimpleName()));
     46     }
     47 
     48     @Test
     49     public void should_call_listeners_in_order() throws Exception {
     50         // given
     51         List<InvocationListener> container = new ArrayList<InvocationListener>();
     52         RememberingListener listener1 = new RememberingListener(container);
     53         RememberingListener listener2 = new RememberingListener(container);
     54 
     55         Foo foo = mock(Foo.class, withSettings().invocationListeners(listener1, listener2));
     56 
     57         // when
     58         foo.giveMeSomeString("herb");
     59 
     60         // then
     61         assertThat(container).containsExactly(listener1, listener2);
     62     }
     63 
     64     @Test
     65     public void should_allow_same_listener() throws Exception {
     66         // given
     67         List<InvocationListener> container = new ArrayList<InvocationListener>();
     68         RememberingListener listener1 = new RememberingListener(container);
     69 
     70         Foo foo = mock(Foo.class, withSettings().invocationListeners(listener1, listener1));
     71 
     72         // when
     73         foo.giveMeSomeString("a");
     74         foo.giveMeSomeString("b");
     75 
     76         // then each listener was notified 2 times (notified 4 times in total)
     77         assertThat(container).containsExactly(listener1, listener1, listener1, listener1);
     78     }
     79 
     80     @Test
     81     public void should_call_all_listener_when_mock_return_normally() throws Exception {
     82         // given
     83         RememberingListener listener1 = new RememberingListener();
     84         RememberingListener listener2 = new RememberingListener();
     85         Foo foo = mock(Foo.class, withSettings().invocationListeners(listener1, listener2));
     86         given(foo.giveMeSomeString("herb")).willReturn("rosemary");
     87 
     88         // when
     89         foo.giveMeSomeString("herb");
     90 
     91         // then
     92         assertThat(listener1).is(notifiedFor("rosemary", getClass().getSimpleName()));
     93         assertThat(listener2).is(notifiedFor("rosemary", getClass().getSimpleName()));
     94     }
     95 
     96     @Test
     97     public void should_call_all_listener_when_mock_throws_exception() throws Exception {
     98         // given
     99         InvocationListener listener1 = mock(InvocationListener.class, "listener1");
    100         InvocationListener listener2 = mock(InvocationListener.class, "listener2");
    101         Foo foo = mock(Foo.class, withSettings().invocationListeners(listener1, listener2));
    102         doThrow(new OvenNotWorking()).when(foo).doSomething("cook");
    103 
    104         // when
    105         try {
    106             foo.doSomething("cook");
    107             fail("Exception expected.");
    108         } catch (OvenNotWorking actualException) {
    109             // then
    110             InOrder orderedVerify = inOrder(listener1, listener2);
    111             orderedVerify.verify(listener1).reportInvocation(any(MethodInvocationReport.class));
    112             orderedVerify.verify(listener2).reportInvocation(any(MethodInvocationReport.class));
    113         }
    114     }
    115 
    116     private static Condition<RememberingListener> notifiedFor(final Object returned, final String location) {
    117         return new Condition<RememberingListener>() {
    118             public boolean matches(RememberingListener toBeAsserted) {
    119                 assertThat(toBeAsserted.returnValue).isEqualTo(returned);
    120                 assertThat(toBeAsserted.invocation).isNotNull();
    121                 assertThat(toBeAsserted.locationOfStubbing).contains(location);
    122                 return true;
    123             }
    124         };
    125     }
    126 
    127     private static class RememberingListener implements InvocationListener {
    128         private final List<InvocationListener> listenerContainer;
    129         DescribedInvocation invocation;
    130         Object returnValue;
    131         String locationOfStubbing;
    132 
    133         RememberingListener(List<InvocationListener> listenerContainer) {
    134             this.listenerContainer = listenerContainer;
    135         }
    136 
    137         RememberingListener() {
    138             this(new ArrayList<InvocationListener>());
    139         }
    140 
    141         public void reportInvocation(MethodInvocationReport mcr) {
    142             this.invocation = mcr.getInvocation();
    143             this.returnValue = mcr.getReturnedValue();
    144             this.locationOfStubbing = mcr.getLocationOfStubbing();
    145             listenerContainer.add(this); //so that we can assert on order
    146         }
    147     }
    148 
    149     private static class OvenNotWorking extends RuntimeException { }
    150 }
    151