text: package com.github.dreamhead.moco;
  
  import com.github.dreamhead.moco.helper.MocoTestHelper;
  import org.apache.http.client.fluent.Request;
  import org.apache.http.message.BasicNameValuePair;
  import org.junit.Before;
  import org.junit.Test;
  import org.mockito.Mockito;
  
  import java.io.IOException;
  
  import static com.github.dreamhead.moco.HttpsCertificate.certificate;
  import static com.github.dreamhead.moco.Moco.by;
  import static com.github.dreamhead.moco.Moco.eq;
  import static com.github.dreamhead.moco.Moco.form;
  import static com.github.dreamhead.moco.Moco.httpServer;
  import static com.github.dreamhead.moco.Moco.httpsServer;
  import static com.github.dreamhead.moco.Moco.log;
  import static com.github.dreamhead.moco.Moco.pathResource;
  import static com.github.dreamhead.moco.Moco.uri;
  import static com.github.dreamhead.moco.MocoRequestHit.atLeast;
  import static com.github.dreamhead.moco.MocoRequestHit.atMost;
  import static com.github.dreamhead.moco.MocoRequestHit.between;
  import static com.github.dreamhead.moco.MocoRequestHit.never;
  import static com.github.dreamhead.moco.MocoRequestHit.once;
  import static com.github.dreamhead.moco.MocoRequestHit.requestHit;
  import static com.github.dreamhead.moco.MocoRequestHit.times;
  import static com.github.dreamhead.moco.MocoRequestHit.unexpected;
  import static com.github.dreamhead.moco.Runner.running;
  import static com.github.dreamhead.moco.helper.RemoteTestUtils.port;
  import static com.github.dreamhead.moco.helper.RemoteTestUtils.remoteHttpsUrl;
  import static com.github.dreamhead.moco.helper.RemoteTestUtils.remoteUrl;
  import static com.github.dreamhead.moco.helper.RemoteTestUtils.root;
  import static org.hamcrest.CoreMatchers.is;
  import static org.junit.Assert.assertThat;
  import static org.mockito.Mockito.any;
  import static org.mockito.Mockito.mock;
  import static org.mockito.Mockito.verify;
  
  public class MocoRequestHitTest {
      private static final HttpsCertificate DEFAULT_CERTIFICATE = certificate(pathResource("cert.jks"), "mocohttps", "mocohttps");
  
      private MocoTestHelper helper;
      private RequestHit hit;
  
      @Before
      public void setUp() throws Exception {
          helper = new MocoTestHelper();
          hit = requestHit();
      }
  
      @Test
      public void should_monitor_server_behavior() throws Exception {
          final MocoMonitor monitor = mock(MocoMonitor.class);
          final HttpServer server = httpServer(port(), monitor);
          server.get(by(uri("/foo"))).response("bar");
  
          running(server, () -> assertThat(helper.get(remoteUrl("/foo")), is("bar")));
  
          verify(monitor).onMessageArrived(any(HttpRequest.class));
          verify(monitor).onMessageLeave(any(HttpResponse.class));
          verify(monitor, Mockito.never()).onException(any(Exception.class));
      }
  
      @Test
      public void should_monitor_server_behavior_without_port() throws Exception {
          final MocoMonitor monitor = mock(MocoMonitor.class);
          final HttpServer server = httpServer(monitor);
          server.get(by(uri("/foo"))).response("bar");
  
          running(server, () -> assertThat(helper.get(remoteUrl(server.port(), "/foo")), is("bar")));
  
          verify(monitor).onMessageArrived(any(HttpRequest.class));
          verify(monitor).onMessageLeave(any(HttpResponse.class));
          verify(monitor, Mockito.never()).onException(any(Exception.class));
      }
  
      @Test
      public void should_verify_expected_request() throws Exception {
          final HttpServer server = httpServer(port(), hit);
          server.get(by(uri("/foo"))).response("bar");
  
          running(server, () -> assertThat(helper.get(remoteUrl("/foo")), is("bar")));
  
          hit.verify(by(uri("/foo")), times(1));
      }
  
      @Test(expected = VerificationException.class)
      public void should_fail_to_verify_while_expectation_can_not_be_met() throws Exception {
          httpServer(port(), hit);
          hit.verify(by(uri("/foo")), times(1));
      }
  
      @Test
      public void should_verify_expected_request_for_at_least() throws Exception {
          final HttpServer server = httpServer(port(), hit);
          server.get(by(uri("/foo"))).response("bar");
  
          running(server, () -> {
              assertThat(helper.get(remoteUrl("/foo")), is("bar"));
              assertThat(helper.get(remoteUrl("/foo")), is("bar"));
          });
  
          hit.verify(by(uri("/foo")), atLeast(1));
      }
  
      @Test
      public void should_verify_expected_request_for_between() throws Exception {
          final HttpServer server = httpServer(port(), hit);
          server.get(by(uri("/foo"))).response("bar");
  
          running(server, () -> {
              assertThat(helper.get(remoteUrl("/foo")), is("bar"));
              assertThat(helper.get(remoteUrl("/foo")), is("bar"));
              assertThat(helper.get(remoteUrl("/foo")), is("bar"));
          });
  
          hit.verify(by(uri("/foo")), between(1, 3));
      }
  
      @Test(expected = VerificationException.class)
      public void should_fail_to_verify_at_least_expected_request_while_expectation_can_not_be_met() throws Exception {
          httpServer(port(), hit);
          hit.verify(by(uri("/foo")), atLeast(1));
      }
  
      @Test
      public void should_verify_expected_request_for_at_most() throws Exception {
          final HttpServer server = httpServer(port(), hit);
          server.get(by(uri("/foo"))).response("bar");
  
          running(server, () -> {
              assertThat(helper.get(remoteUrl("/foo")), is("bar"));
              assertThat(helper.get(remoteUrl("/foo")), is("bar"));
          });
  
          hit.verify(by(uri("/foo")), atMost(2));
      }
  
      @Test(expected = VerificationException.class)
      public void should_fail_to_verify_at_most_expected_request_while_expectation_can_not_be_met() throws Exception {
          final HttpServer server = httpServer(port(), hit);
          server.get(by(uri("/foo"))).response("bar");
          running(server, () -> {
              assertThat(helper.get(remoteUrl("/foo")), is("bar"));
              assertThat(helper.get(remoteUrl("/foo")), is("bar"));
          });
  
          hit.verify(by(uri("/foo")), atMost(1));
      }
  
      @Test
      public void should_verify_expected_request_for_once() throws Exception {
          final HttpServer server = httpServer(port(), hit);
          server.get(by(uri("/foo"))).response("bar");
  
          running(server, () -> assertThat(helper.get(remoteUrl("/foo")), is("bar")));
  
          hit.verify(by(uri("/foo")), once());
      }
  
      @Test(expected = VerificationException.class)
      public void should_fail_to_verify_while_once_expectation_can_not_be_met() throws Exception {
          httpServer(port(), hit);
          hit.verify(by(uri("/foo")), times(1));
      }
  
      @Test
      public void should_verify_unexpected_request_without_unexpected_request() throws Exception {
          final HttpServer server = httpServer(port(), hit);
          server.get(by(uri("/foo"))).response("bar");
  
          running(server, () -> assertThat(helper.get(remoteUrl("/foo")), is("bar")));
  
          hit.verify(unexpected(), never());
      }
  
      @Test
      public void should_verify_unexpected_request_with_unexpected_request() throws Exception {
          final HttpServer server = httpServer(port(), hit);
  
          running(server, () -> {
              try {
                  helper.get(remoteUrl("/foo"));
              } catch (IOException ignored) {
              }
          });
  
          hit.verify(unexpected(), times(1));
      }
  
      @Test(expected = VerificationException.class)
      public void should_fail_to_verify_while_unexpected_request_expectation_can_not_be_met() throws Exception {
          final HttpServer server = httpServer(port(), hit);
  
          running(server, () -> {
              try {
                  helper.get(remoteUrl("/foo"));
              } catch (IOException ignored) {
              }
          });
  
          hit.verify(unexpected(), never());
      }
  
      @Test(expected = IllegalArgumentException.class)
      public void should_throw_exception_for_negative_number_for_times() {
          times(-1);
      }
  
      @Test
      public void should_verify_form_data() throws Exception {
          final HttpServer server = httpServer(port(), hit);
          server.post(eq(form("name"), "dreamhead")).response("foobar");
  
          running(server, () -> {
              Request request = Request.Post(root()).bodyForm(new BasicNameValuePair("name", "dreamhead"));
              String content = helper.executeAsString(request);
              assertThat(content, is("foobar"));
          });
  
          hit.verify(eq(form("name"), "dreamhead"), once());
      }
  
      @Test
      public void should_verify_form_data_even_if_no_server_expectation() throws Exception {
          final HttpServer server = httpServer(port(), hit);
          server.response("foobar");
  
          running(server, () -> {
              Request request = Request.Post(root()).bodyForm(new BasicNameValuePair("name", "dreamhead"));
              String content = helper.executeAsString(request);
              assertThat(content, is("foobar"));
          });
  
          hit.verify(eq(form("name"), "dreamhead"), once());
      }
  
      @Test
      public void should_verify_expected_request_and_log_at_same_time() throws Exception {
          final HttpServer server = httpServer(port(), hit, log());
          server.get(by(uri("/foo"))).response("bar");
  
          running(server, () -> assertThat(helper.get(remoteUrl("/foo")), is("bar")));
  
          hit.verify(by(uri("/foo")), times(1));
      }
  
      @Test
      public void should_verify_expected_request_and_log_at_same_time_for_https() throws Exception {
          final HttpServer server = httpsServer(port(), DEFAULT_CERTIFICATE, hit, log());
          server.get(by(uri("/foo"))).response("bar");
  
          running(server, () -> assertThat(helper.get(remoteHttpsUrl("/foo")), is("bar")));
  
          hit.verify(by(uri("/foo")), times(1));
      }
  }
  