HTTP unit tests

Demonstrates how to unit test an HTTP function.

Documentation pages that include this code sample

To view the code sample used in context, see the following documentation:

Code sample

C#

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging.Abstractions;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace HelloHttp.Tests
{
    public class FunctionUnitTest
    {
        [Fact]
        public async Task GetRequest_NoParameters()
        {
            DefaultHttpContext context = new DefaultHttpContext();
            string text = await ExecuteRequest(context);
            Assert.Equal("Hello world!", text);
        }

        [Fact]
        public async Task GetRequest_UrlParameters()
        {
            DefaultHttpContext context = new DefaultHttpContext
            {
                Request = { QueryString = new QueryString("?name=Cho") }
            };
            string text = await ExecuteRequest(context);
            Assert.Equal("Hello Cho!", text);
        }

        [Fact]
        public async Task PostRequest_BodyParameters()
        {
            string json = "{\"name\":\"Julie\"}";
            DefaultHttpContext context = new DefaultHttpContext
            {
                Request =
                {
                    Method = HttpMethods.Post,
                    Body = new MemoryStream(Encoding.UTF8.GetBytes(json))
                }
            };
            string text = await ExecuteRequest(context);
            Assert.Equal("Hello Julie!", text);
        }

        /// <summary>
        /// Executes the given request in the function, validates that the response
        /// status code is 200, and returns the text of the response body.
        /// </summary>
        private static async Task<string> ExecuteRequest(HttpContext context)
        {
            MemoryStream responseStream = new MemoryStream();
            context.Response.Body = responseStream;

            Function function = new Function(new NullLogger<Function>());
            await function.HandleAsync(context);
            Assert.Equal(200, context.Response.StatusCode);
            context.Response.BodyWriter.Complete();
            context.Response.Body.Position = 0;

            TextReader reader = new StreamReader(responseStream);
            return reader.ReadToEnd();
        }
    }
}

C++

#include <google/cloud/functions/http_request.h>
#include <google/cloud/functions/http_response.h>
#include <gtest/gtest.h>

namespace gcf = ::google::cloud::functions;
extern gcf::HttpResponse hello_world_http(gcf::HttpRequest request);

namespace {

TEST(HttpUnitTest, Success) {
  auto actual = hello_world_http(
      gcf::HttpRequest{}.set_payload(R"js({ "name": "Foo" })js"));
  EXPECT_EQ(actual.payload(), "Hello Foo!");

  actual = hello_world_http(
      gcf::HttpRequest{}.set_payload(R"js({ "unused": 7 })js"));
  EXPECT_EQ(actual.payload(), "Hello World!");

  actual = hello_world_http(gcf::HttpRequest{}.set_payload("Bar"));
  EXPECT_EQ(actual.payload(), "Hello World!");
}

}  // namespace

Go


package helloworld

import (
	"net/http/httptest"
	"strings"
	"testing"
)

func TestHelloHTTP(t *testing.T) {
	tests := []struct {
		body string
		want string
	}{
		{body: `{"name": ""}`, want: "Hello, World!"},
		{body: `{"name": "Gopher"}`, want: "Hello, Gopher!"},
	}

	for _, test := range tests {
		req := httptest.NewRequest("GET", "/", strings.NewReader(test.body))
		req.Header.Add("Content-Type", "application/json")

		rr := httptest.NewRecorder()
		HelloHTTP(rr, req)

		if got := rr.Body.String(); got != test.want {
			t.Errorf("HelloHTTP(%q) = %q, want %q", test.body, got, test.want)
		}
	}
}

Java


import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;

import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Map;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@RunWith(JUnit4.class)
public class HelloHttpTest {
  @Mock private HttpRequest request;
  @Mock private HttpResponse response;

  private BufferedWriter writerOut;
  private StringWriter responseOut;
  private static final Gson gson = new Gson();

  @Before
  public void beforeTest() throws IOException {
    MockitoAnnotations.initMocks(this);

    // use an empty string as the default request content
    BufferedReader reader = new BufferedReader(new StringReader(""));
    when(request.getReader()).thenReturn(reader);

    responseOut = new StringWriter();
    writerOut = new BufferedWriter(responseOut);
    when(response.getWriter()).thenReturn(writerOut);
  }

  @Test
  public void helloHttp_noParamsGet() throws IOException {
    new HelloHttp().service(request, response);

    writerOut.flush();
    assertThat(responseOut.toString()).isEqualTo("Hello world!");
  }
}

Node.js

const assert = require('assert');
const sinon = require('sinon');
const uuid = require('uuid');

const {helloHttp} = require('..');

it('helloHttp: should print a name', () => {
  // Mock ExpressJS 'req' and 'res' parameters
  const name = uuid.v4();
  const req = {
    query: {},
    body: {
      name: name,
    },
  };
  const res = {send: sinon.stub()};

  // Call tested function
  helloHttp(req, res);

  // Verify behavior of tested function
  assert.ok(res.send.calledOnce);
  assert.deepStrictEqual(res.send.firstCall.args, [`Hello ${name}!`]);
});

PHP


namespace Google\Cloud\Samples\Functions\HelloworldHttp;

use GuzzleHttp\Psr7\ServerRequest;
use PHPUnit\Framework\TestCase;

/**
 * Class SampleUnitTest.
 *
 * Unit test for helloHttp.
 */
class SampleUnitTest extends TestCase
{
    public static function setUpBeforeClass(): void
    {
        require_once __DIR__ . '/index.php';
    }

    public function testFunction(): void
    {
        $name = uniqid();
        $request = new ServerRequest('POST', '/', [], json_encode(['name' => $name]));
        $expected = sprintf('Hello, %s!', $name);
        $actual = helloHttp($request);
        $this->assertEquals($expected, $actual);
    }
}

Python

from unittest.mock import Mock

import main


def test_print_name():
    name = 'test'
    data = {'name': name}
    req = Mock(get_json=Mock(return_value=data), args=data)

    # Call tested function
    assert main.hello_http(req) == 'Hello {}!'.format(name)


def test_print_hello_world():
    data = {}
    req = Mock(get_json=Mock(return_value=data), args=data)

    # Call tested function
    assert main.hello_http(req) == 'Hello World!'

Ruby

require "minitest/autorun"
require "functions_framework/testing"

describe "functions_helloworld_http" do
  include FunctionsFramework::Testing

  it "prints a name" do
    load_temporary "helloworld/http/app.rb" do
      request = make_post_request "http://example.com:8080/", '{"name": "Ruby"}'
      response = call_http "hello_http", request
      assert_equal 200, response.status
      assert_equal "Hello Ruby!", response.body.join
    end
  end

  it "prints hello world" do
    load_temporary "helloworld/http/app.rb" do
      request = make_post_request "http://example.com:8080/", ""
      response = call_http "hello_http", request
      assert_equal 200, response.status
      assert_equal "Hello World!", response.body.join
    end
  end
end

What's next

To search and filter code samples for other Google Cloud products, see the Google Cloud sample browser.