I am changing and endpoint in my express backend that would typically make 1 http request to a vendor's API to create a payment object in their system for a previously created account.
The previously created account is currently created by sending a POST request to the vendor's API at /partner/v3/account
. I then save their response into our db, amongst other details, so we can retrieve it later.
Due to some changes in specs, whenever the payment object is requested, we have to re-create the account. The payment request looks up the previously created account in the db and used to use the account id to make the payment request to the vendor. However, due to the spec changes, before we do the payment request, we have to re-create the account using the previously created account details and sending a new POST request to /partner/v3/account
. Only after the account has been re-created, can we proceed with the payment request.
In my original jest
tests I had something like the following and it worked fine:
describe("POST /v1/accounts/:accountId/payment", () => {
beforeAll(async () => {
// nock vendor response for initial creation of account
nock(VENDOR_URL)
.post("/partner/v3/account")
.reply(HttpStatus.CREATED, createRes1);
// post to internal endpoint to create the initial account
// this saves response and other details to db for retrieval
await request(app)
.post("/v1/accounts")
.send(createReq);
}
it("should return successful payment object for user account", async() => {
nock(VENDOR_URL)
.post("/payments/setup", paymentReq)
.reply(HttpStatus.CREATED, paymentRes);
// this endpoint retrieves the previously created account
// uses account id to make payment request
const response = await request(app)
.post(`/v1/accounts/${accountId}/payment`)
.send({
"paymentFreq": "Monthly"
});
expect(response.status).toEqual(HttpStatus.OK);
}
}
However, with the need to re-create the account, I had to change the code to make another http request to the vendor's API to re-create the account. In the above code, the nock
I have in BeforeAll
seems to be called once, as expected, but the test fails, presumably because the second vendor API request in not being mocked properly.
How do I handle mocking the same vendor endpoint to be called at different times in the code. It seems that:
- mocking it once in
BeforeAll
and once in theit
block does not work - mocking it twice in
BeforeAll
does not work, usingtimes(2)
- mocking it twice in the
it
block does not work
Note: When I say it does not work, what I mean is that when the POST request to /v1/accounts/${accountId}/payment
I expect that the previously created account should be retrieved, per the BeforeAll
commands. However, if I mock the response from /partner/v3/account
in my it
test, instead of retrieving the account created by BeforeAll
, I get the mocked account from within the it
statement.
it("should return successful payment object for user account", async() => {
// mock response of re-creating account
nock(VENDOR_URL)
.post("/partner/v3/account")
.reply(HttpStatus.CREATED, createRes2);
// mock response of making account payment
nock(VENDOR_URL)
.post("/payments/setup", paymentReq)
.reply(HttpStatus.CREATED, paymentRes);
// this endpoint retrieves the previously created account
// uses previous account details to re-created account
// uses new account id to make payment request
const response = await request(app)
.post(`/v1/accounts/${accountId}/payment`)
.send({
"paymentFreq": "Monthly"
});
expect(response.status).toEqual(HttpStatus.OK);
}
Note: I need to nock
the /partner/v3/account
endpoint call such that each call returns something different, since the point is testing a re-creation of an account, so the account id will be different on the response from the vendor. My mocked response has a different account id, so this should be true, but as noted previously, the first time the account is retrieved in /v1/accounts/${accountId}/payment
it gets the second mocked response instead of the first one from BeforeAll
.
Not the solution I want, but using times seems to at least mock the response to the vendor's API
N
times, in this case, twice.It is not the best solution because in the first request to the vendor's API to create the account, an account id is created and this should be different in the next request, but at least it gets me closer to what i need.
I ended up up with the following in my
it
statement:I tried to mock the response from POSTing to this endpoint in a chained manner, and it did not work: