Reputation: 4229
I'd like to mock the node Stripe SDK in Jest because I don't want to run the mock API server from Stripe but I can't figure how how to do it. I'm creating a __mocks__
directory and adding stripe.js
but I can't get anything usable to export.
I typically get TypeError: Cannot read property 'create' of undefined
when calling strypegw.charges.create()
. I'm using ES6 module syntax so I import stripe from 'stripe'
.
Upvotes: 18
Views: 14562
Reputation: 5731
As of [email protected]
, you can add a direct spyOn
to the Customer
class instead of overriding the entire Stripe class.
Short answer:
jest.mock('stripe', () => {
const stripe = jest.requireActual('stripe');
jest.spyOn(stripe.resources.Customers.prototype, 'create')
.mockImplementation(() => (
Promise.resolve({id: 'stripe-test-id'})
));
return stripe;
})
Long answer:
Stripe
class because there are a lot of static values and utility helpers your application might use such as Stripe.errors.StripeError
. It would be superfluous to mock things that don't need mocking.Stripe.prototype.customer
doesn't work because .customer
is not a method until after instantiation. See https://github.com/stripe/stripe-node/blob/master/lib/stripe.js#L124Stripe.resources
. So you can spy on the resources directly. When the real Stripe gets instantiated, it'll reference the spies instead of the real class for the particular resource you're trying to mock. See https://github.com/stripe/stripe-node/blob/master/lib/stripe.js#L51Stripe.resources.Customers = {create: jest.fn()};
. I would not recommend it for reasons stated in point 1.Upvotes: 5
Reputation: 2839
Add this in a helper function and invoke it in jest setup file or at the top of the test when required.
// Mocking Stripe object
const elementMock = {
mount: jest.fn(),
destroy: jest.fn(),
on: jest.fn(),
update: jest.fn(),
};
const elementsMock = {
create: jest.fn().mockReturnValue(elementMock),
};
const stripeMock = {
elements: jest.fn().mockReturnValue(elementsMock),
createToken: jest.fn(() => Promise.resolve()),
createSource: jest.fn(() => Promise.resolve()),
};
// Set the global Stripe
window.Stripe = jest.fn().mockReturnValue(stripeMock);
With this approach, you can easily test your stripe related code as well
// Ex. of a token successfully created mock
stripeMock.createToken.mockResolvedValue({
token: {
id: 'test_id',
},
});
// Ex. of a failure mock
stripeMock.createToken.mockResolvedValue({
error: {
code: 'incomplete_number',
message: 'Your card number is incomplete.',
type: 'validation_error',
},
});
Upvotes: 0
Reputation: 1159
Here is a simple solution :
jest.mock("stripe", () => {
return jest.fn().mockImplementation(function {
return {
charges: {
create: () => "fake stripe response",
},
};
});
});
I found it in jest documentation about ES6 Class Mocks
Upvotes: 2
Reputation: 350
// your-code.js
const stripe = require('stripe')('key');
const customer = await stripe.customers.create({
...
});
// __mocks__/stripe.js
class Stripe {}
const stripe = jest.fn(() => new Stripe());
module.exports = stripe;
module.exports.Stripe = Stripe;
// stripe.tests.js
const { Stripe } = require('stripe');
const createCustomerMock = jest.fn(() => ({
id: 1,
...
}));
Stripe.prototype.customers = {
create: createCustomerMock,
};
Upvotes: 16