// Adds a service and returns it's ID.
        //
        // Do not use this to test the ServiceFunctions.AddService method.
        // This was designed to help other tests and assumes that the
        // ServiceFunctions.AddService has already been tested.
        private static string AddService(string method, string path)
        {
            var bodyString = @"# BodyString
# Request
Method: {0}
Path: {1}

# Response
ContentType: application/json
StatusCode: 200

# Body
{""color"":""Red""}";

            var request = new TestHttpRequest()
            {
                Method     = "POST",
                Path       = "/__vs/services",
                BodyString = bodyString
                             .Replace("{0}", method)
                             .Replace("{1}", path)
            };
            var response = new TestHttpResponse();
            var context  = new TestHttpContext(request, response);

            Task next() => Task.CompletedTask;

            ServiceFunctions.AddService(context, next).Wait();
            return(response.ReadBody());
        }
        public void ServiceFunctions_AddService_InvokesNextFunctionWhenMethodNotPOST()
        {
            // Arrange
            #region BodyString
            var bodyString = @"# BodyString
# This ""GET"" is irrelevant
Method: GET
Path: /api/things/53";
            #endregion

            var request = new TestHttpRequest()
            {
                // This "GET" causes the request not to match the required pattern.
                Method     = "GET",
                Path       = "/__vs/services",
                BodyString = bodyString
            };
            var response = new TestHttpResponse();
            var context  = new TestHttpContext(request, response);

            var numCallsToNext = 0;
            Task next()
            {
                numCallsToNext++;
                return(Task.CompletedTask);
            }

            // Act
            ServiceFunctions.AddService(context, next).Wait();

            // Assert
            Assert.AreEqual(1, numCallsToNext);
        }
        public void ServiceFunctions_AddService_ReturnsOkAndServiceId()
        {
            // Arrange
            #region BodyString
            var bodyString = @"# BodyString
Method: GET
Path: /api/things/53";
            #endregion

            var request = new TestHttpRequest()
            {
                Method     = "POST",
                Path       = "/__vs/services",
                BodyString = bodyString
            };
            var response = new TestHttpResponse();
            var context = new TestHttpContext(request, response);
            Task next() => Task.CompletedTask;

            // Act
            ServiceFunctions.AddService(context, next).Wait();

            // Assert
            Assert.AreEqual(200, response.StatusCode);
            Assert.AreEqual("text/plain", response.ContentType);
            Assert.IsTrue(Guid.TryParse(response.ReadBody(), out Guid serviceId));
            Assert.AreNotEqual(Guid.Empty, serviceId);
        }
        public void ServiceFunctions_AddService_ThrowsOnNullNextFunction()
        {
            // Arrange
            HttpContext context          = new TestHttpContext();
            Func <Task> nullNextFunction = null;

            // Act
            ServiceFunctions.AddService(context, nullNextFunction).Wait();
        }
        public void ServiceFunctions_AddService_ThrowsOnNullContext()
        {
            // Arrange
            HttpContext nullContext = null;

            Task next() => Task.CompletedTask;

            // Act
            ServiceFunctions.AddService(nullContext, next).Wait();
        }
        public void ServiceFunctions_AddService_ThrowsDuplicateService()
        {
            // Arrange
            #region BodyString
            var bodyString = @"# BodyString
Method: GET
Path: /api/things/53";
            #endregion

            var request = new TestHttpRequest()
            {
                Method     = "POST",
                Path       = "/__vs/services",
                BodyString = bodyString
            };
            var response = new TestHttpResponse();
            var context = new TestHttpContext(request, response);
            Task next() => Task.CompletedTask;

            // Act
            ServiceFunctions.AddService(context, next).Wait();
            ServiceFunctions.AddService(context, next).Wait();
        }
        public void ServiceFunctions_AddService_ThrowsOnMissingPath()
        {
            // Arrange
            #region BodyString
            var bodyString = @"# BodyString
Method: GET
# Commenting out the Path setting should cause a failure.
# Path: /api/things/53";
            #endregion

            var request = new TestHttpRequest()
            {
                Method     = "POST",
                Path       = "/__vs/services",
                BodyString = bodyString
            };
            var response = new TestHttpResponse();
            var context = new TestHttpContext(request, response);
            Task next() => Task.CompletedTask;

            // Act
            ServiceFunctions.AddService(context, next).Wait();
        }