DEV Community

Cover image for Mocking Google Cloud Storage Objects with Java
Diogo Dantas Moreira
Diogo Dantas Moreira

Posted on • Updated on

Mocking Google Cloud Storage Objects with Java

Google Cloud Storage is widely used as a cloud storage service to allow users to store and retrieve objects. When working with Google Cloud Storage, it's essential to write efficient unit tests to ensure the application behaves as expected.

Introduction

One common challenge in unit testing is dealing with external dependencies, that's when we use mocks such as Blob Objects from Google Cloud Storage, which may not be readily available during testing or needs to be mocked due to pricing restrictions. This blog post will explore how to mock Blob Objects from Google Cloud Storage for efficient unit testing.

A note about mocks

Mocks are objects that simulate the behavior of real objects, allowing developers to isolate and test specific components of their code.

Suppose you have a class with many dependencies (references to other classes). When you're writing a test for that specific class, you want to make sure that every time this test fails, the feedback should say something about problems in the class in question. That's why we use mocks, by substituting real dependencies with mock objects, developers can control the behavior and responses of these dependencies, making it easier to create focused and reliable tests

Mocks are particularly useful when testing interactions between different parts of a system, as they help identify and fix bugs or design flaws early on. Additionally, mocks facilitate testing in complex scenarios where certain dependencies may be unavailable or difficult to set up, that's the case in this article.

Understand Google Cloud Storage objects

Google Cloud Storage offers storage classes and objects for managing data in the cloud. In Java, you can use the Google Cloud Storage client library to interact with these features. Here's a brief example of some of them

// Create a storage client
Storage storage = StorageOptions
        .getDefaultInstance().getService();

// Upload an object to a bucket
BlobId blobId = BlobId.of("my-bucket", "my-object");
BlobInfo blobInfo = BlobInfo.newBuilder(blobId).build();
storage.create(blobInfo, "Hello, Cloud Storage!".getBytes());

// List objects in a bucket
Page<Blob> blobs = storage.list("my-bucket");
for (Blob b : blobs.iterateAll()) {
    System.out.println(b.getName());
}

// Delete an object from a bucket
boolean deleted = storage.delete("my-bucket", "my-object");
if (deleted) {
    System.out.println("Object deleted successfully.");
}
Enter fullscreen mode Exit fullscreen mode

So far, we can see that the storage object is the one that does most of the job here. And that's the one we should mock in our case.

Using Google Cloud NIO to mock storage

Google has an in-memory emulator you can use from the Google Cloud NIO. First, we must add the dependency in our pom.xml. Bear in mind that a newer version can be available by the time you're reading this post.

<dependency>
  <groupId>com.google.cloud</groupId>
  <artifactId>google-cloud-nio</artifactId>
  <version>0.126.15</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Or if you use Gradle.

implementation 'com.google.cloud:google-cloud-nio:0.126.15'
Enter fullscreen mode Exit fullscreen mode

And then, during our tests, we can use the LocalStorageHelper object to create a fake storage to mock Google Cloud.

Storage storage = LocalStorageHelper.getOptions().getService();
Enter fullscreen mode Exit fullscreen mode

From now on, we can keep using storage to create the files inside the buckets and download them in the same way we'll do in the production code.

BlobInfo blobInfo = BlobInfo.newBuilder(
                BlobId.of("my-mock-bucket", "my-mock-object"))
        .build();
storage.create(blobInfo, "A file text".getBytes());

// Later, we can 'download' this file to do
// what is expected from our application.
Blob blob = storage.get("my-mock-bucket", "my-mock-object");
byte[] content = blob.getContent();
System.out.println(new String(content));
Enter fullscreen mode Exit fullscreen mode

If you're writing an application on top of Spring Boot, for example, you can also create a configuration class for your tests to "overwrite" the default Storage object that is created by default.

@TestConfiguration
public class CloudStorageConfiguration {

  @Bean
  public Storage createMockStorage() throws IOException {
    Storage storage = LocalStorageHelper
              .getOptions().getService();
    BlobInfo blobInfo = BlobInfo.newBuilder(
        BlobId.of("my-mock-bucket", "my-mock-object"))
        .build();
    // Create some file that you want to use and reflect the
    // one you expect from your Cloud Storage bucket
    Path path = Path.of(
        "src", "test", "resources", "test-resource.txt");
    byte[] content = Files.readAllBytes(path);
    storage.create(blobInfo, content);
    return storage;
  }

}
Enter fullscreen mode Exit fullscreen mode

And that's it. Hope this short post added value to your learning and helped you with testing your Java application that has some integration with Google Cloud Storage.

Any feedback or suggestions are welcome.

Top comments (1)

Collapse
 
nahoj profile image
Johan Grande

Thanks!