Skip to content

Deep partial overrides

Part Factory lets you override only the values that matter for a test.

For object factories, overrides are deep partials. That means every property is optional, including properties nested inside other objects.

Given this object shape:

interface UserProfile {
username: string;
contact: {
email: string;
phone: string;
address: { line1: string; city: string; country: string };
};
}

A factory can provide a complete default object:

import { StaticFactory } from "@kensio/part-factory";
const userProfileFactory = new StaticFactory({
username: "foo_user",
contact: {
email: "foo@example.com",
phone: "123456789",
address: { line1: "1 Foo Street", city: "London", country: "UK" },
},
});

When you make an object, you can override any combination of nested values without altering the rest of the structure:

const userProfile = userProfileFactory.make({
contact: {
address: {
city: "Manchester",
},
},
});

The result keeps the default values everywhere else:

{
"username": "foo_user",
"contact": {
"email": "foo@example.com",
"phone": "123456789",
"address": {
"line1": "1 Foo Street",
"city": "Manchester",
"country": "UK"
}
}
}

Without deep partial overrides, changing contact.address.city would require you to provide the whole contact object, including email, phone, address.line1, and address.country.

With Part Factory, each test can focus on the values relevant to that test:

const londonUser = userProfileFactory.make();
const manchesterUser = userProfileFactory.make({
contact: { address: { city: "Manchester" } },
});
const renamedUser = userProfileFactory.make({ username: "bar_user" });

This keeps tests shorter and avoids repeating unrelated default data.

TypeScript still checks overrides.

userProfileFactory.make({ contact: { address: { city: "Manchester" } } });

TypeScript knows that city must be a string, and it knows which nested properties exist.

This means an invalid override is rejected:

userProfileFactory.make({ contact: { address: { city: 123 } } });
// TypeScript will catch the invalid type for `city`.

Deep partial overrides are designed for normal object-shaped test entities.

Some values are treated as complete values rather than objects to recursively override. For example, functions and Date values are kept as whole values.

Arrays can be overridden with arrays of partial items:

interface Order {
id: string;
lines: {
sku: string;
quantity: number;
}[];
}
const order = orderFactory.make({
lines: [
{
quantity: 2,
},
],
});

In most test code, you do not need to think about the implementation details. You can pass the small partial override that describes the case you are testing, and Part Factory combines it with the factory defaults.