Einheitentest für Cloud Storage (2. Generation)

Beispiel für einen Einheitentest für eine durch Cloud Storage ausgelöste Funktion, die in Cloud Functions (2nd gen) ausgeführt wird.

Codebeispiel

C#

Richten Sie die Standardanmeldedaten für Anwendungen ein, um sich bei Cloud Functions zu authentifizieren. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

using CloudNative.CloudEvents;
using Google.Cloud.Functions.Testing;
using Google.Events;
using Google.Events.Protobuf.Cloud.Storage.V1;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
using Xunit;

namespace HelloWorld.Tests;

public class HelloGcsUnitTest
{
    [Fact]
    public async Task FileNameIsLogged()
    {
        // Prepare the inputs
        var data = new StorageObjectData { Name = "new-file.txt" };
        var cloudEvent = new CloudEvent
        {
            Type = StorageObjectData.FinalizedCloudEventType,
            Source = new Uri("//storage.googleapis.com", UriKind.RelativeOrAbsolute),
            Id = "1234",
            Data = data
        };
        var logger = new MemoryLogger<HelloGcs.Function>();

        // Execute the function
        var function = new HelloGcs.Function(logger);
        await function.HandleAsync(cloudEvent, data, CancellationToken.None);

        // Check the log results - just the entry starting with "File:".
        var logEntry = Assert.Single(logger.ListLogEntries(), entry => entry.Message.StartsWith("File:"));
        Assert.Equal("File: new-file.txt", logEntry.Message);
        Assert.Equal(LogLevel.Information, logEntry.Level);
    }
}

Go

Richten Sie die Standardanmeldedaten für Anwendungen ein, um sich bei Cloud Functions zu authentifizieren. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.


package helloworld

import (
	"context"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"testing"
	"time"

	"github.com/cloudevents/sdk-go/v2/event"
	"github.com/googleapis/google-cloudevents-go/cloud/storagedata"
	"google.golang.org/protobuf/encoding/protojson"
	"google.golang.org/protobuf/types/known/timestamppb"
)

func TestHelloStorage(t *testing.T) {
	r, w, _ := os.Pipe()
	log.SetOutput(w)
	originalFlags := log.Flags()
	log.SetFlags(log.Flags() &^ (log.Ldate | log.Ltime))

	d := &storagedata.StorageObjectData{
		Name:        "hello_gcs.txt",
		TimeCreated: timestamppb.New(time.Now()),
	}

	jsonData, err := protojson.Marshal(d)
	if err != nil {
		t.Fatalf("protojson.Marshal: %v", err)
	}

	e := event.New()
	e.SetDataContentType("application/json")
	e.SetData(e.DataContentType(), jsonData)

	helloStorage(context.Background(), e)

	w.Close()
	log.SetOutput(os.Stderr)
	log.SetFlags(originalFlags)

	out, err := ioutil.ReadAll(r)
	if err != nil {
		t.Fatalf("ReadAll: %v", err)
	}
	got := string(out)
	if want := d.Name; strings.Contains(want, got) {
		t.Errorf("HelloStorage = %q, want to contain %q", got, want)
	}
	if want := d.TimeCreated.String(); strings.Contains(want, got) {
		t.Errorf("HelloStorage = %q, want to contain %q", got, want)
	}
}

Java

Richten Sie die Standardanmeldedaten für Anwendungen ein, um sich bei Cloud Functions zu authentifizieren. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.


import static com.google.common.truth.Truth.assertThat;

import com.google.common.testing.TestLogHandler;
import com.google.events.cloud.storage.v1.StorageObjectData;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Timestamp;
import com.google.protobuf.util.JsonFormat;
import io.cloudevents.CloudEvent;
import io.cloudevents.core.builder.CloudEventBuilder;
import java.net.URI;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Unit tests for main.java.com.example.functions.helloworld.HelloGcs. */
@RunWith(JUnit4.class)
public class HelloGcsTest {
  private static final TestLogHandler LOG_HANDLER = new TestLogHandler();
  private static final Logger logger = Logger.getLogger(HelloGcs.class.getName());

  @BeforeClass
  public static void beforeClass() throws Exception {
    logger.addHandler(LOG_HANDLER);
  }

  @After
  public void afterTest() {
    LOG_HANDLER.clear();
  }

  @Test
  public void helloGcs_shouldPrintFileName() throws InvalidProtocolBufferException {
    // Create event data
    String file = "foo.txt";
    String bucket = "gs://test-bucket";

    // Get the current time in milliseconds
    long millis = System.currentTimeMillis();

    // Create a Timestamp object
    Timestamp timestamp = Timestamp.newBuilder()
        .setSeconds(millis / 1000)
        .setNanos((int) ((millis % 1000) * 1000000))
        .build();

    StorageObjectData.Builder dataBuilder = StorageObjectData.newBuilder()
        .setName(file)
        .setBucket(bucket)
        .setMetageneration(10)
        .setTimeCreated(timestamp)
        .setUpdated(timestamp);

    String jsonData = JsonFormat.printer().print(dataBuilder);

    // Construct a CloudEvent
    CloudEvent event = CloudEventBuilder.v1()
        .withId("0")
        .withType("google.storage.object.finalize")
        .withSource(URI.create("https://example.com"))
        .withData("application/json", jsonData.getBytes())
        .build();

    new HelloGcs().accept(event);

    String actualBucket = LOG_HANDLER.getStoredLogRecords().get(2).getMessage();
    String actualFile = LOG_HANDLER.getStoredLogRecords().get(3).getMessage();
    assertThat(actualFile).contains("File: " + file);
    assertThat(actualBucket).contains("Bucket: " + bucket);
  }

  @Test
  public void helloGcs_shouldPrintNotifyIfDataIsNull() throws InvalidProtocolBufferException {
    // Construct a CloudEvent
    CloudEvent event = CloudEventBuilder.v1()
        .withId("0")
        .withType("google.storage.object.finalize")
        .withSource(URI.create("https://example.com"))
        .build();

    new HelloGcs().accept(event);

    String logMessage = LOG_HANDLER.getStoredLogRecords().get(2).getMessage();
    assertThat(logMessage).isEqualTo("No data found in cloud event payload!");
  }
}

Node.js

Richten Sie die Standardanmeldedaten für Anwendungen ein, um sich bei Cloud Functions zu authentifizieren. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

const {getFunction} = require('@google-cloud/functions-framework/testing');

describe('functions_cloudevent_storage', () => {
  const assert = require('assert');
  const sinon = require('sinon');
  require('..');

  const stubConsole = function () {
    sinon.stub(console, 'error');
    sinon.stub(console, 'log');
  };

  const restoreConsole = function () {
    console.log.restore();
    console.error.restore();
  };

  beforeEach(stubConsole);
  afterEach(restoreConsole);

  it('helloGCS: should print out event', () => {
    const event = {
      id: '1234',
      type: 'mock-gcs-event',
      data: {
        bucket: 'my-bucket',
        name: 'my-file.txt',
      },
    };

    // Call tested function and verify its behavior
    const helloGCS = getFunction('helloGCS');
    helloGCS(event);

    assert(console.log.calledWith('Event ID: 1234'));
    assert(console.log.calledWith('Event Type: mock-gcs-event'));
    assert(console.log.calledWith('Bucket: my-bucket'));
    assert(console.log.calledWith('File: my-file.txt'));
  });
});

PHP

Richten Sie die Standardanmeldedaten für Anwendungen ein, um sich bei Cloud Functions zu authentifizieren. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.


namespace Google\Cloud\Samples\Functions\HelloworldStorage\Test;

use CloudEvents\V1\CloudEventImmutable;
use CloudEvents\V1\CloudEventInterface;

use PHPUnit\Framework\TestCase;

/**
 * Class SampleUnitTest.
 *
 * Unit test for 'Helloworld Storage' Cloud Function.
 */
class SampleUnitTest extends TestCase
{
    /**
     * Include the Cloud Function code before running any tests.
     *
     * @see https://phpunit.readthedocs.io/en/latest/fixtures.html
     */
    public static function setUpBeforeClass(): void
    {
        require_once __DIR__ . '/index.php';
    }

    public function dataProvider()
    {
        return [
            [
                'cloudevent' => new CloudEventImmutable(
                    uniqId(), // id
                    'storage.googleapis.com', // source
                    'google.cloud.storage.object.v1.finalized', // type
                    [
                        'bucket' => 'some-bucket',
                        'metageneration' => '1',
                        'name' => 'folder/friendly.txt',
                        'timeCreated' => '2020-04-23T07:38:57.230Z',
                        'updated' => '2020-04-23T07:38:57.230Z',
                    ] // data
                ),
                'statusCode' => '200',
            ],
        ];
    }

    /**
     * @dataProvider dataProvider
     */
    public function testFunction(CloudEventInterface $cloudevent): void
    {
        // Capture function output by overriding the function's logging behavior.
        // The 'LOGGER_OUTPUT' environment variable must be used in your function:
        //
        // $log = fopen(getenv('LOGGER_OUTPUT') ?: 'php://stderr', 'wb');
        // fwrite($log, 'Log Entry');
        putenv('LOGGER_OUTPUT=php://output');
        helloGCS($cloudevent);
        // Provided by PHPUnit\Framework\TestCase.
        $actual = $this->getActualOutput();

        // Test output includes the properties provided in the CloudEvent.
        foreach ($cloudevent->getData() as $property => $value) {
            $this->assertStringContainsString($value, $actual);
        }
        $this->assertStringContainsString($cloudevent->getId(), $actual);
        $this->assertStringContainsString($cloudevent->getType(), $actual);
    }
}

Python

Richten Sie die Standardanmeldedaten für Anwendungen ein, um sich bei Cloud Functions zu authentifizieren. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.


from cloudevents.http import CloudEvent
import pytest

import main

def test_functions_eventsource_storage(capsys: pytest.LogCaptureFixture) -> None:
    attributes = {
        "id": "5e9f24a",
        "type": "google.cloud.storage.object.v1.finalized",
        "source": "sourceUrlHere",
    }

    data = {
        "bucket": "test_bucket_for_storage",
        "name": "new_blob_uploaded",
        "generation": 1,
        "metageneration": 1,
        "timeCreated": "2021-10-10 00:00:00.000000Z",
        "updated": "2021-11-11 00:00:00.000000Z",
    }

    event = CloudEvent(attributes, data)

    (
        event_id,
        event_type,
        bucket,
        name,
        metageneration,
        timeCreated,
        updated,
    ) = main.hello_gcs(event)

    out, _ = capsys.readouterr()
    assert "5e9f24a" in event_id
    assert "google.cloud.storage.object.v1.finalized" in event_type
    assert "test_bucket_for_storage" in bucket
    assert "new_blob_uploaded" in name
    assert metageneration == 1
    assert "2021-10-10 00:00:00.000000Z" in timeCreated
    assert "2021-11-11 00:00:00.000000Z" in updated

Nächste Schritte

Informationen zum Suchen und Filtern von Codebeispielen für andere Google Cloud-Produkte finden Sie im Google Cloud-Beispielbrowser.