Skip to content

Azurite

Install

1
npm install @testcontainers/azurite --save-dev

Examples

These examples use the following libraries:

Choose an image from the container registry and substitute IMAGE.

Upload/download a blob

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
await using container = await new AzuriteContainer(IMAGE).start();

const connectionString = container.getConnectionString();
const serviceClient = BlobServiceClient.fromConnectionString(connectionString);
const containerClient = serviceClient.getContainerClient("test");
await containerClient.createIfNotExists();

const blobName = "hello.txt";
const content = "Hello world!";
await containerClient.uploadBlockBlob(blobName, content, Buffer.byteLength(content));

const blobClient = containerClient.getBlockBlobClient(blobName);
const downloadBuffer = await blobClient.downloadToBuffer();
expect(downloadBuffer.toString()).toBe(content);

Send/receive queue messages

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
await using container = await new AzuriteContainer(IMAGE).start();

const connectionString = container.getConnectionString();
const serviceClient = QueueServiceClient.fromConnectionString(connectionString);
const queueName = "test-queue";
await serviceClient.createQueue(queueName);

const messageText = "Hello world!";
const queueClient = serviceClient.getQueueClient(queueName);
await queueClient.sendMessage(messageText);

const messages = await queueClient.receiveMessages();
expect(messages.receivedMessageItems).toMatchObject([{ messageText }]);

Create/insert/fetch on a table

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
await using container = await new AzuriteContainer(IMAGE).start();

const connectionString = container.getConnectionString();
const tableName = "person";
const tableClient = TableClient.fromConnectionString(connectionString, tableName, {
  allowInsecureConnection: true,
});
await tableClient.createTable();

const entity: TableEntity<{ name: string }> = {
  partitionKey: "p1",
  rowKey: "r1",
  name: "John Doe",
};
await tableClient.createEntity(entity);

const nextEntity = await tableClient.listEntities().next();
expect(nextEntity.value).toEqual(expect.objectContaining(entity));

In memory persistence

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
await using container = await new AzuriteContainer(IMAGE).withInMemoryPersistence().start();

const blobName = "hello.txt";

{
  const connectionString = container.getConnectionString();
  const serviceClient = BlobServiceClient.fromConnectionString(connectionString);
  const containerClient = serviceClient.getContainerClient("test");
  await containerClient.createIfNotExists();
  const content = "Hello world!";
  await containerClient.uploadBlockBlob(blobName, content, Buffer.byteLength(content));
  const blobClient = containerClient.getBlockBlobClient(blobName);
  const blobExists = await blobClient.exists();
  expect(blobExists).toBeTruthy();
}

await container.restart();

{
  const connectionString = container.getConnectionString();
  const serviceClient = BlobServiceClient.fromConnectionString(connectionString);
  const containerClient = serviceClient.getContainerClient("test");
  const blobClient = containerClient.getBlockBlobClient(blobName);
  const blobExistsAfterRestart = await blobClient.exists();
  expect(blobExistsAfterRestart).toBeFalsy();
}

With credentials

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const accountName = "test-account";
const accountKey = Buffer.from("test-key").toString("base64");

await using container = await new AzuriteContainer(IMAGE)
  .withAccountName(accountName)
  .withAccountKey(accountKey)
  .start();

const credentials = new StorageSharedKeyCredential(accountName, accountKey);
const serviceClient = new BlobServiceClient(container.getBlobEndpoint(), credentials);

With ports

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
const blobPort = 13000;
const queuePort = 14000;
const tablePort = 15000;

await using container = await new AzuriteContainer(IMAGE)
  .withBlobPort({ container: 10001, host: blobPort })
  .withQueuePort({ container: 10002, host: queuePort })
  .withTablePort({ container: 10003, host: tablePort })
  .start();

expect(container.getBlobPort()).toBe(blobPort);
expect(container.getQueuePort()).toBe(queuePort);
expect(container.getTablePort()).toBe(tablePort);

With HTTPS (PEM certificate)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
await using container = await new AzuriteContainer(IMAGE).withSsl(TEST_CERT, TEST_KEY).start();

const connectionString = container.getConnectionString();
expect(connectionString).toContain("DefaultEndpointsProtocol=https");
expect(connectionString).toContain("BlobEndpoint=https://");
expect(connectionString).toContain("QueueEndpoint=https://");
expect(connectionString).toContain("TableEndpoint=https://");

const serviceClient = BlobServiceClient.fromConnectionString(connectionString, getTlsPipelineOptions(TEST_CERT));
const containerClient = serviceClient.getContainerClient("test");
await containerClient.createIfNotExists();

const containerItem = await serviceClient.listContainers().next();
expect(containerItem.value?.name).toBe("test");
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
type BlobClientPipelineOptions = NonNullable<Parameters<typeof BlobServiceClient.fromConnectionString>[1]>;
type BlobClientPipelineOptionsWithTls = BlobClientPipelineOptions & { tlsOptions: { ca: string } };

const base64UrlEncode = (value: string): string => Buffer.from(value).toString("base64url");

const createJwtToken = (payload: Record<string, string | number>): string => {
  const header = { alg: "none", typ: "JWT" };
  return `${base64UrlEncode(JSON.stringify(header))}.${base64UrlEncode(JSON.stringify(payload))}.`;
};

export const getTlsPipelineOptions = (ca: string): BlobClientPipelineOptionsWithTls => ({
  tlsOptions: {
    ca,
  },
});

export const createOAuthToken = (audience: string): string => {
  const now = Math.floor(Date.now() / 1000);

  return createJwtToken({
    nbf: now - 60,
    iat: now - 60,
    exp: now + 3600,
    iss: "https://sts.windows.net/ab1f708d-50f6-404c-a006-d71b2ac7a606/",
    aud: audience,
    scp: "user_impersonation",
    oid: "23657296-5cd5-45b0-a809-d972a7f4dfe1",
    tid: "dd0d0df1-06c3-436c-8034-4b9a153097ce",
  });
};

export const createTokenCredential = (token: string): TokenCredential => ({
  getToken: async () => ({
    token,
    expiresOnTimestamp: Date.now() + 3600_000,
  }),
});

With OAuth (basic)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
await using container = await new AzuriteContainer(IMAGE).withSsl(TEST_CERT, TEST_KEY).withOAuth().start();

const validServiceClient = new BlobServiceClient(
  container.getBlobEndpoint(),
  createTokenCredential(createOAuthToken("https://storage.azure.com")),
  getTlsPipelineOptions(TEST_CERT)
);
const validContainerClient = validServiceClient.getContainerClient(`oauth-valid-${Date.now()}`);
await validContainerClient.create();
await validContainerClient.delete();

const invalidServiceClient = new BlobServiceClient(
  container.getBlobEndpoint(),
  createTokenCredential(createOAuthToken("https://invalidaccount.blob.core.windows.net")),
  getTlsPipelineOptions(TEST_CERT)
);
const invalidContainerClient = invalidServiceClient.getContainerClient(`oauth-invalid-${Date.now()}`);
await expect(invalidContainerClient.create()).rejects.toThrow("Server failed to authenticate the request");
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
type BlobClientPipelineOptions = NonNullable<Parameters<typeof BlobServiceClient.fromConnectionString>[1]>;
type BlobClientPipelineOptionsWithTls = BlobClientPipelineOptions & { tlsOptions: { ca: string } };

const base64UrlEncode = (value: string): string => Buffer.from(value).toString("base64url");

const createJwtToken = (payload: Record<string, string | number>): string => {
  const header = { alg: "none", typ: "JWT" };
  return `${base64UrlEncode(JSON.stringify(header))}.${base64UrlEncode(JSON.stringify(payload))}.`;
};

export const getTlsPipelineOptions = (ca: string): BlobClientPipelineOptionsWithTls => ({
  tlsOptions: {
    ca,
  },
});

export const createOAuthToken = (audience: string): string => {
  const now = Math.floor(Date.now() / 1000);

  return createJwtToken({
    nbf: now - 60,
    iat: now - 60,
    exp: now + 3600,
    iss: "https://sts.windows.net/ab1f708d-50f6-404c-a006-d71b2ac7a606/",
    aud: audience,
    scp: "user_impersonation",
    oid: "23657296-5cd5-45b0-a809-d972a7f4dfe1",
    tid: "dd0d0df1-06c3-436c-8034-4b9a153097ce",
  });
};

export const createTokenCredential = (token: string): TokenCredential => ({
  getToken: async () => ({
    token,
    expiresOnTimestamp: Date.now() + 3600_000,
  }),
});