/* * Copyright (c) 2012 - 2016 Jadler contributors * This program is made available under the terms of the MIT License. */ package net.jadler.matchers; import net.jadler.exception.JadlerException; import net.jadler.Request; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.StringDescription; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.junit.Before; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.hamcrest.Matchers.is; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) public class RequestMatcherTest { private static final String MATCHER_DESC = "retrieved value is"; private static final String INNER_MATCHER_DESC = "matched by a mock matcher"; private static final String INNER_MATCHER_MISMATCH_DESC = "was not matched"; private static final Object RETRIEVED_VALUE = new Object(); @Mock private Matcher<Object> mockInnerMatcher; @Before public void setUp() { //define what to do when describeTo is called on the mockMatcher instance doAnswer(new Answer<Void>() { @Override public Void answer(final InvocationOnMock invocation) { final Description arg = (Description) invocation.getArguments()[0]; arg.appendText(INNER_MATCHER_DESC); return null; } }).when(this.mockInnerMatcher).describeTo(any(Description.class)); doAnswer(new Answer<Void>() { @Override public Void answer(final InvocationOnMock invocation) { final Description arg = (Description) invocation.getArguments()[1]; arg.appendText(INNER_MATCHER_MISMATCH_DESC); return null; } }).when(this.mockInnerMatcher).describeMismatch(eq(RETRIEVED_VALUE), any(Description.class)); } @Test(expected=IllegalArgumentException.class) public void constructor() { new TestRequestMatcher(mockInnerMatcher); new TestRequestMatcher(null); fail("inner matcher cannot be null"); } @Test public void testDescribeMismatch() { final Matcher<?> rm = new TestRequestMatcher(mockInnerMatcher); final Request req = mock(Request.class); final Description desc = new StringDescription(); rm.describeMismatch(req, desc); assertThat(desc.toString(), is( "REQUIRED: " + MATCHER_DESC + " " + INNER_MATCHER_DESC + " BUT " + INNER_MATCHER_MISMATCH_DESC)); } @Test public void describeTo() { final Matcher<?> rm = new TestRequestMatcher(mockInnerMatcher); final Description desc = new StringDescription(); rm.describeTo(desc); assertThat(desc.toString(), is(MATCHER_DESC + " " + INNER_MATCHER_DESC)); } @Test public void matchesObject() { final Matcher<?> rm = new TestRequestMatcher(mockInnerMatcher); //it's not a Request instance, must be false assertThat(rm.matches(new Object()), is(false)); } @Test public void matchesNull() { final Matcher<?> rm = new TestRequestMatcher(mockInnerMatcher); //it's not a Request instance, must be false assertThat(rm.matches(null), is(false)); } @Test(expected=JadlerException.class) public void matchesException() { final Request request = mock(Request.class); final Matcher<?> rm = new TestRequestMatcher(mockInnerMatcher) { @Override public Object retrieveValue(Request req) throws Exception { throw new Exception(); } }; rm.matches(request); } @Test public void matches() { final Request request = mock(Request.class); when(this.mockInnerMatcher.matches(eq(RETRIEVED_VALUE))).thenReturn(true); final Matcher<?> rm = new TestRequestMatcher(mockInnerMatcher); //since the inner matcher returns true, the result must be true as well assertThat(rm.matches(request), is(true)); //verify the inner matcher was given the value retrieved from the http request verify(this.mockInnerMatcher, times(1)).matches(eq(RETRIEVED_VALUE)); verifyNoMoreInteractions(this.mockInnerMatcher); } @Test public void notMatches() { final Request request = mock(Request.class); when(this.mockInnerMatcher.matches(eq(RETRIEVED_VALUE))).thenReturn(false); final Matcher<?> rm = new TestRequestMatcher(mockInnerMatcher); //since the inner matcher returns false, the result must be true as well assertThat(rm.matches(request), is(false)); //verify the inner matcher was given the value retrieved from the http request verify(this.mockInnerMatcher, times(1)).matches(eq(RETRIEVED_VALUE)); verifyNoMoreInteractions(this.mockInnerMatcher); } /** * Non-abstract extension of the tested RequestMatcher abstract class */ private class TestRequestMatcher extends RequestMatcher<Object> { public TestRequestMatcher(final Matcher<Object> innerMatcher) { super(innerMatcher); } @Override public Object retrieveValue(final Request req) throws Exception { return RETRIEVED_VALUE; } @Override public String provideDescription() { return MATCHER_DESC; } } }