| /* |
| * Copyright (c) 2018 Mockito contributors |
| * This program is made available under the terms of the MIT License. |
| */ |
| package org.mockitousage.debugging; |
| |
| import org.junit.Test; |
| import org.mockito.ArgumentMatcher; |
| import org.mockito.InOrder; |
| import org.mockito.listeners.StubbingLookupEvent; |
| import org.mockito.listeners.StubbingLookupListener; |
| import org.mockito.mock.MockCreationSettings; |
| import org.mockitousage.IMethods; |
| import org.mockitoutil.ConcurrentTesting; |
| import org.mockitoutil.TestBase; |
| |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.fail; |
| import static org.mockito.Mockito.*; |
| |
| public class StubbingLookupListenerCallbackTest extends TestBase { |
| |
| StubbingLookupListener listener = mock(StubbingLookupListener.class); |
| StubbingLookupListener listener2 = mock(StubbingLookupListener.class); |
| Foo mock = mock(Foo.class, withSettings().stubbingLookupListeners(listener)); |
| |
| @Test |
| public void should_call_listener_when_mock_return_normally_with_stubbed_answer() { |
| // given |
| doReturn("coke").when(mock).giveMeSomeString("soda"); |
| doReturn("java").when(mock).giveMeSomeString("coffee"); |
| |
| // when |
| mock.giveMeSomeString("soda"); |
| |
| // then |
| verify(listener).onStubbingLookup(argThat(new ArgumentMatcher<StubbingLookupEvent>() { |
| @Override |
| public boolean matches(StubbingLookupEvent argument) { |
| assertEquals("soda", argument.getInvocation().getArgument(0)); |
| assertEquals("mock", argument.getMockSettings().getMockName().toString()); |
| assertEquals(2, argument.getAllStubbings().size()); |
| assertNotNull(argument.getStubbingFound()); |
| return true; |
| } |
| })); |
| } |
| |
| @Test |
| public void should_call_listener_when_mock_return_normally_with_default_answer() { |
| // given |
| doReturn("java").when(mock).giveMeSomeString("coffee"); |
| |
| // when |
| mock.giveMeSomeString("soda"); |
| |
| // then |
| verify(listener).onStubbingLookup(argThat(new ArgumentMatcher<StubbingLookupEvent>() { |
| @Override |
| public boolean matches(StubbingLookupEvent argument) { |
| assertEquals("soda", argument.getInvocation().getArgument(0)); |
| assertEquals("mock", argument.getMockSettings().getMockName().toString()); |
| assertEquals(1, argument.getAllStubbings().size()); |
| assertNull(argument.getStubbingFound()); |
| return true; |
| } |
| })); |
| } |
| |
| @Test |
| public void should_not_call_listener_when_mock_is_not_called() { |
| // when stubbing is recorded |
| doReturn("java").when(mock).giveMeSomeString("coffee"); |
| |
| // then |
| verifyZeroInteractions(listener); |
| } |
| |
| @Test |
| public void should_allow_same_listener() { |
| // given |
| Foo mock = mock(Foo.class, withSettings().stubbingLookupListeners(listener, listener)); |
| |
| // when |
| mock.giveMeSomeString("tea"); |
| mock.giveMeSomeString("coke"); |
| |
| // then each listener was notified 2 times (notified 4 times in total) |
| verify(listener, times(4)).onStubbingLookup(any(StubbingLookupEvent.class)); |
| } |
| |
| @Test |
| public void should_call_all_listeners_in_order() { |
| // given |
| Foo mock = mock(Foo.class, withSettings().stubbingLookupListeners(listener, listener2)); |
| doReturn("sprite").when(mock).giveMeSomeString("soda"); |
| |
| // when |
| mock.giveMeSomeString("soda"); |
| |
| // then |
| InOrder inOrder = inOrder(listener, listener2); |
| inOrder.verify(listener).onStubbingLookup(any(StubbingLookupEvent.class)); |
| inOrder.verify(listener2).onStubbingLookup(any(StubbingLookupEvent.class)); |
| } |
| |
| @Test |
| public void should_call_all_listeners_when_mock_throws_exception() { |
| // given |
| Foo mock = mock(Foo.class, withSettings().stubbingLookupListeners(listener, listener2)); |
| doThrow(new NoWater()).when(mock).giveMeSomeString("tea"); |
| |
| // when |
| try { |
| mock.giveMeSomeString("tea"); |
| fail(); |
| } catch (NoWater e) { |
| // then |
| verify(listener).onStubbingLookup(any(StubbingLookupEvent.class)); |
| verify(listener2).onStubbingLookup(any(StubbingLookupEvent.class)); |
| } |
| } |
| |
| @Test |
| public void should_delete_listener() { |
| // given |
| Foo mock = mock(Foo.class, withSettings().stubbingLookupListeners(listener, listener2)); |
| |
| // when |
| mock.doSomething("1"); |
| mockingDetails(mock).getMockCreationSettings().getStubbingLookupListeners().remove(listener2); |
| mock.doSomething("2"); |
| |
| // then |
| verify(listener, times(2)).onStubbingLookup(any(StubbingLookupEvent.class)); |
| verify(listener2, times(1)).onStubbingLookup(any(StubbingLookupEvent.class)); |
| } |
| |
| @Test |
| public void should_clear_listeners() { |
| // given |
| Foo mock = mock(Foo.class, withSettings().stubbingLookupListeners(listener, listener2)); |
| |
| // when |
| mockingDetails(mock).getMockCreationSettings().getStubbingLookupListeners().clear(); |
| mock.doSomething("foo"); |
| |
| // then |
| verifyZeroInteractions(listener, listener2); |
| } |
| |
| @Test |
| public void add_listeners_concurrently_sanity_check() throws Exception { |
| //given |
| final IMethods mock = mock(IMethods.class); |
| final MockCreationSettings<?> settings = mockingDetails(mock).getMockCreationSettings(); |
| |
| List<Runnable> runnables = new LinkedList<Runnable>(); |
| for (int i = 0; i < 50; i++) { |
| runnables.add(new Runnable() { |
| public void run() { |
| StubbingLookupListener listener1 = mock(StubbingLookupListener.class); |
| StubbingLookupListener listener2 = mock(StubbingLookupListener.class); |
| settings.getStubbingLookupListeners().add(listener1); |
| settings.getStubbingLookupListeners().add(listener2); |
| settings.getStubbingLookupListeners().remove(listener1); |
| } |
| }); |
| } |
| |
| //when |
| ConcurrentTesting.concurrently(runnables.toArray(new Runnable[runnables.size()])); |
| |
| //then |
| //This assertion may be flaky. If it is let's fix it or remove the test. For now, I'm keeping the test. |
| assertEquals(50, settings.getStubbingLookupListeners().size()); |
| } |
| |
| private static class NoWater extends RuntimeException {} |
| } |