Reputation: 2623
I'm reviewing some test-covered TypeScript (using Jest) that checks the return of some mandatory properties. However, some of these tests are checking what should happen if some of the mandatory properties are not set and I'm unsure how to best cover this in a typed way.
Here's an example of one of the functions:
const getPrice = (product: Product): number => product.price || 0;
The interface for Product is:
interface Product {
name: string;
price: number;
}
And the test:
describe('getPrice', () => {
it('returns the price from the given order', () => {
const mockProduct: Product = {name: 'mock product', price: 100};
expect(getPrice(mockProduct)).toBe(100);
});
it('returns 0 if price is not defined in the given order', () => {
const mockProduct: Product = {name: 'mock product'}; // Bad - Product requires price
expect(getPrice(mockProduct)).toBe(0);
});
});
The second test asserts against a lack of price
property, however this is mandatory. I assume this is done because the real system may unexpectedly not have a price
(the data comes from another service).
If so, should the price
property in the interface be changed to optional? And would that also mean all properties that come from services should be optional?
Upvotes: 0
Views: 125
Reputation: 1513
I think you should emulate the real situation in your test. In the getPrice
function "point of view", it can receive anything from an external service.
So it makes sense to set your partial test object as unknown
and cast it to Product
in your function call.
This way you're asserting to the typing system that you know what you're doing: "believe me! it's a Product
here... i swear it!" 😀
Like this:
it('returns 0 if price is not defined in the given order', () => {
const mockProduct: unknown = {name: 'mock product'}; // Bad - Product requires price
expect(getPrice(mockProduct as Product)).toBe(0);
});
Upvotes: 2
Reputation: 2912
Totally depends on your usages. If you are making the types in your own code everywhere, you don't really have to test for undefined as you pointed out. Having said that, if you take them in from anywhere, or force cast anywhere then you are SOL.
Personally I don't worry about test types being perfect. So I would just make a Partial and then cast it
value as unknown as YourType
Will force it back to the correct type, but not require you to change application code at all. (Basically simulate outside values coming in)
Upvotes: 1