-
-
Save nfarina/90ba99a5187113900c86289e67586aaa to your computer and use it in GitHub Desktop.
| // | |
| // Quick & Dirty Google Cloud Storage emulator for tests. Requires | |
| // `stream-buffers` from npm. Use it like this: | |
| // | |
| // `new MockStorage().bucket('my-bucket').file('my_file').createWriteStream()` | |
| // | |
| class MockStorage { | |
| buckets: {[name: string]: MockBucket}; | |
| constructor() { | |
| this.buckets = {}; | |
| } | |
| bucket(name: string) { | |
| return this.buckets[name] || | |
| (this.buckets[name] = new MockBucket(name)); | |
| } | |
| } | |
| class MockBucket { | |
| name: string; | |
| files: {[path: string]: MockFile}; | |
| constructor(name: string) { | |
| this.name = name; | |
| this.files = {}; | |
| } | |
| file(path: string) { | |
| return this.files[path] || | |
| (this.files[path] = new MockFile(path)); | |
| } | |
| } | |
| class MockFile { | |
| path: string; | |
| contents: Buffer; | |
| metadata: Object; | |
| constructor(path: string) { | |
| this.path = path; | |
| this.contents = new Buffer(0); | |
| this.metadata = {}; | |
| } | |
| get() { | |
| return [this, this.metadata]; | |
| } | |
| setMetadata(metadata: Object) { | |
| const customMetadata = {...this.metadata.metadata, ...metadata.metadata}; | |
| this.metadata = {...this.metadata, ...metadata, metadata: customMetadata}; | |
| } | |
| createReadStream() { | |
| const streamBuffers = require('stream-buffers'); | |
| const readable = new streamBuffers.ReadableStreamBuffer(); | |
| readable.put(this.contents); | |
| readable.stop(); | |
| return readable; | |
| } | |
| createWriteStream({metadata}: Object) { | |
| this.setMetadata(metadata); | |
| const streamBuffers = require('stream-buffers'); | |
| const writable = new streamBuffers.WritableStreamBuffer(); | |
| writable.on('finish', () => { | |
| this.contents = writable.getContents(); | |
| }); | |
| return writable; | |
| } | |
| delete() { | |
| return Promise.resolve(); | |
| } | |
| } |
add delete method to MockFile returning a resolved promise.
Added, thanks!
There is also good enough to add upload method to MockBucket
upload(path: string, options: any) {
return [this.file(path)];
}and add makePublic method to MockFile
async makePublic() {
return [
{ bucket: 'test-bucket', object: 'test-object' },
]
}your code was help a lot :D
Glad to hear it!
hey man, you should publish an npm package of this, what you think? If you allow, i do it.
Sure I’m happy to turn this into a proper repo and npm package, if people are finding it useful.
Would be userful for me, please, do it :)
No package yet? 😅
TS Example I've been using from the example above, I wanted to contribute back as it was a big help.
/* eslint-disable @typescript-eslint/no-unused-vars */
//
// Quick & Dirty Google Cloud Storage emulator for tests. Requires
// `stream-buffers` from npm. Use it like this:
//
// `new MockStorage().bucket('my-bucket').file('my_file').createWriteStream()`
//
import type { CreateWriteStreamOptions, GetSignedUrlConfig } from '@google-cloud/storage';
import streamBuffers from 'stream-buffers';
export class MockStorage {
public buckets: object;
public constructor() {
this.buckets = {};
}
public bucket(name: string): MockBucket {
if (this.buckets[name] === undefined) {
this.buckets[name] = new MockBucket(name);
}
return this.buckets[name];
}
}
export class MockBucket {
public name: string;
public files: object;
public constructor(name: string) {
this.name = name;
this.files = {};
}
public upload(name: string, options: any): MockFile[] {
return [this.file(name)];
}
public file(name: string): MockFile {
if (this.files[name] === undefined) {
this.files[name] = new MockFile(name);
}
return this.files[name];
}
}
interface Metadata {
metadata?: object;
}
export class MockFile {
public name: string;
public path?: string;
public contents: Buffer;
public metadata: {
metadata?: object;
};
public constructor(name: string, path?: string) {
this.name = name;
this.path = path;
this.contents = Buffer.alloc(0);
this.metadata = {};
}
public get(): [MockFile, any] {
return [this, this.metadata];
}
public async delete(): Promise<void> {
return Promise.resolve();
}
public exists(): [boolean, any] {
return [true, this.metadata];
}
public setMetadata(metadata: Metadata): void {
const customMetadata = { ...this.metadata.metadata, ...metadata.metadata };
this.metadata = { ...this.metadata, ...metadata, metadata: customMetadata };
}
public async getSignedUrl(options?: GetSignedUrlConfig): Promise<string> {
return Promise.resolve('https://example.com');
}
public createReadStream(): any {
const readable = new streamBuffers.ReadableStreamBuffer();
readable.put(this.contents);
readable.stop();
return readable;
}
public createWriteStream(options?: CreateWriteStreamOptions): any {
const writable = new streamBuffers.WritableStreamBuffer();
writable.on('finish', () => {
this.contents = writable.getContents();
});
return writable;
}
}Hi, how do you actually inject it into jest mocking? Thanks!
Hi, how do you actually inject it into
jestmocking? Thanks!
I personally run all my Firebase calls through a single getFirebaseApp() sort of function. When running under test mode, it returns a mock App that stubs out the getters for mock Storage, Firestore, etc.
Should be able to use https://jestjs.io/docs/mock-functions#mocking-modules, or https://www.npmjs.com/package/proxyquire. Both should be able to mock out the actual call to '@google-cloud/storage'
I am making some progress with this approach:
function mockedStorage() {
return class MockStorage {
public buckets: MockBucketList;
public constructor() {
this.buckets = {};
}
public bucket(name: string): MockBucket {
if (this.buckets[name] === undefined) {
this.buckets[name] = new MockBucket(name);
}
return this.buckets[name];
}
};
}
jest.mock('@google-cloud/storage', () => ({
Storage: mockedStorage()
}));Hi everyone! Just wanted to share that I recently published a small package to help mock @google-cloud/storage written in TypeScript. Check out mock-gcs: https://github.com/aldipermanaetikaputra/mock-gcs. Hope it helps!
@aldipermanaetikaputra I have a Datastore one if you'd like that as well. I couldn't find this packages repo so I couldn't file issues or contribute back. https://www.npmjs.com/package/datastore-mock?activeTab=readme So I forked it to a script. Would be nice if it could get maintained and updated.
I have a rather-insane Firestore one as well :) actually works...but it only implements the "compat" API
add delete method to MockFile returning a resolved promise.