Challenge #2: Signature Shielding
Before adding any more tests, you’ll factor out a helper function to make the tests simpler and easier to understand. This is the Signature Shielding pattern.
Instructions
-
Extract a helper method with this signature:
const { httpRequests } = await transformAsync({ port, text, correlationId });
- Make the parameters to
transformAsync()
optional.
Remember to commit your changes when you’re done.
Useful Constants
const IRRELEVANT_PORT = 42;
This constant is available in the test code. Use it when the ROT-13 service’s port doesn’t matter.
const IRRELEVANT_TEXT = "irrelevant_text";
This constant is available in the test code. Use it when the text to encode doesn’t matter.
const IRRELEVANT_CORRELATION_ID = "irrelevant-correlation-id";
This constant is available in the test code. Use it when the correlation ID doesn’t matter.
JavaScript Primers
Hints
1
Before you can factor out the helper method, you need to make your code look like the function you want to factor out.
Introduce variables for the test-specific constants in the “Arrange” and “Act” section and put them at the top of the test.
it("makes request", async () => {
const port = 9999;
const text = "text_to_transform";
const correlationId = "my-correlation-id";
// Arrange
const httpClient = HttpClient.createNull();
const httpRequests = httpClient.trackRequests();
const rot13Client = new Rot13Client(httpClient);
// Act
await rot13Client.transformAsync(port, text, correlationId);
// Assert
assert.deepEqual(httpRequests.data, [{
host: HOST,
port: 9999,
path: "/rot13/transform",
method: "post",
headers: {
"content-type": "application/json",
"x-correlation-id": "my-correlation-id",
},
body: JSON.stringify({ text: "text_to_transform" }),
}]);
});
2
Extract the “Arrange” and “Act” sections of the test into a function named transformAsync()
. Remember the async
keyword, and don’t forget to await
it.
Your editor might have an automated refactoring to do this for you.
it("makes request", async () => {
const port = 9999;
const text = "text_to_transform";
const correlationId = "my-correlation-id";
const httpRequests = await transformAsync(port, text, correlationId);
// Assert
assert.deepEqual(httpRequests.data, [{
host: HOST,
port: 9999,
path: "/rot13/transform",
method: "post",
headers: {
"content-type": "application/json",
"x-correlation-id": "my-correlation-id",
},
body: JSON.stringify({ text: "text_to_transform" }),
}]);
});
async function transformAsync(port, text, correlationId) {
// Arrange
const httpClient = HttpClient.createNull();
const httpRequests = httpClient.trackRequests();
const rot13Client = new Rot13Client(httpClient);
// Act
await rot13Client.transformAsync(port, text, correlationId);
return httpRequests;
}
TypeScript requires types for the function parameters:
async function transformAsync(port: number, text: string, correlationId: string) {
// Arrange
const httpClient = HttpClient.createNull();
const httpRequests = httpClient.trackRequests();
const rot13Client = new Rot13Client(httpClient);
// Act
await rot13Client.transformAsync(port, text, correlationId);
return httpRequests;
}
3
Modify transformAsync()
’s parameters and return value to match the desired signature.
You’ll need to use object shorthand and object destructuring in the test and transformAsync()
.
it("makes request", async () => {
const port = 9999;
const text = "text_to_transform";
const correlationId = "my-correlation-id";
const { httpRequests } = await transformAsync({ port, text, correlationId });
// Assert
assert.deepEqual(httpRequests.data, [{
host: HOST,
port: 9999,
path: "/rot13/transform",
method: "post",
headers: {
"content-type": "application/json",
"x-correlation-id": "my-correlation-id",
},
body: JSON.stringify({ text: "text_to_transform" }),
}]);
});
async function transformAsync({ port, text, correlationId }) {
// Arrange
const httpClient = HttpClient.createNull();
const httpRequests = httpClient.trackRequests();
const rot13Client = new Rot13Client(httpClient);
// Act
await rot13Client.transformAsync(port, text, correlationId);
return { httpRequests };
}
TypeScript still requires types, but now they’re declared for the object parameter:
async function transformAsync(
{ port, text, correlationId }:
{ port: number, text: string, correlationId: string}
) {
// Arrange
const httpClient = HttpClient.createNull();
const httpRequests = httpClient.trackRequests();
const rot13Client = new Rot13Client(httpClient);
// Act
await rot13Client.transformAsync(port, text, correlationId);
return { httpRequests };
}
4
Finish up the refactoring by removing unnecessary variables, comments, and whitespace.
Your editor might have an automatic “Inline Variable” refactoring.
it("makes request", async () => {
const { httpRequests } = await transformAsync({
port: 9999,
text: "text_to_transform",
correlationId: "my-correlation-id"
});
assert.deepEqual(httpRequests.data, [{
host: HOST,
port: 9999,
path: "/rot13/transform",
method: "post",
headers: {
"content-type": "application/json",
"x-correlation-id": "my-correlation-id",
},
body: JSON.stringify({ text: "text_to_transform" }),
}]);
});
async function transformAsync({ port, text, correlationId }) {
const httpClient = HttpClient.createNull();
const httpRequests = httpClient.trackRequests();
const rot13Client = new Rot13Client(httpClient);
await rot13Client.transformAsync(port, text, correlationId);
return { httpRequests };
}
Complete Solution
Test code (JavaScript):
describe.only("ROT-13 Service client", () => {
describe("happy path", () => {
it("makes request", async () => {
const { httpRequests } = await transformAsync({
port: 9999,
text: "text_to_transform",
correlationId: "my-correlation-id"
});
assert.deepEqual(httpRequests.data, [{
host: HOST,
port: 9999,
path: "/rot13/transform",
method: "post",
headers: {
"content-type": "application/json",
"x-correlation-id": "my-correlation-id",
},
body: JSON.stringify({ text: "text_to_transform" }),
}]);
});
// ...
});
async function transformAsync({ port, text, correlationId }) {
const httpClient = HttpClient.createNull();
const httpRequests = httpClient.trackRequests();
const rot13Client = new Rot13Client(httpClient);
await rot13Client.transformAsync(port, text, correlationId);
return { httpRequests };
}
Test code (TypeScript):
describe.only("ROT-13 Service client", () => {
describe("happy path", () => {
it("makes request", async () => {
const { httpRequests } = await transformAsync({
port: 9999,
text: "text_to_transform",
correlationId: "my-correlation-id"
});
assert.deepEqual(httpRequests.data, [{
host: HOST,
port: 9999,
path: "/rot13/transform",
method: "post",
headers: {
"content-type": "application/json",
"x-correlation-id": "my-correlation-id",
},
body: JSON.stringify({ text: "text_to_transform" }),
}]);
});
// ...
});
async function transformAsync(
{ port, text, correlationId }:
{ port: number, text: string, correlationId: string }
) {
const httpClient = HttpClient.createNull();
const httpRequests = httpClient.trackRequests();
const rot13Client = new Rot13Client(httpClient);
await rot13Client.transformAsync(port, text, correlationId);
return { httpRequests };
}
Production code is unchanged.