willryan / factory.ts

A library to ease creation of factories for test data for Typescript
MIT License
425 stars 23 forks source link

How to randomise nested object key in `buildList` #78

Open MRwt48 opened 1 year ago

MRwt48 commented 1 year ago

BuildList only randomizes the first level key value.

Example:

const factory = Factory.Sync.makeFactory({
    randomItem: Factory.each(()=> radomValueGenerator())  // using faker-js
    someObject: {
        randomNestedItem: Factory.each(()=> radomValueGenerator())
    }
})

const results = factory.buildList(3);

Expected

[
    {
        randomItem: "random value 1",
        someObject: {
            randomNestedItem: "random nested value 1",
        }
    },
    {
        randomItem: "random value 2",
        someObject: {
            randomNestedItem: "random nested value 2",
        }
    },
    {
        randomItem: "random value 3",
        someObject: {
            randomNestedItem: "random nested value 3"
        }
    }
]

Actual

[
    {
        randomItem: "random value 1",
        someObject: {
            randomNestedItem: Generator,
        }
    },
    {
        randomItem: "random value 2",
        someObject: {
            randomNestedItem: Generator
        }
    },
    {
        randomItem: "random value 3",
        someObject: {
            randomNestedItem: Generator
        }
    }
]

Also tried using

const factory = Factory.Sync.makeFactory({
    ...
    someObject: Factory.Sync.makeFactory({
        randomNestedItem: Factory.each(()=> radomValueGenerator())
    }).build()
})

but I get

[
    {
        randomItem: "random value 1",
        someObject: {
            randomNestedItem: "random nested value 1", // same value repeated
        }
    },
    {
        randomItem: "random value 2",
        someObject: {
            randomNestedItem: "random nested value 1", // same value repeated
        }
    },
    {
        randomItem: "random value 3",
        someObject: {
            randomNestedItem: "random nested value 1", // same value repeated
        }
    }
]
SendDerek commented 1 year ago

👍 I'm seeing the same issue.

My workaround was to create a new interface for the nested item and create it's own factory:

Child object:

const childObjectFactory = Factory.Sync.makeFactory<MachineTotalUsage>({
  hours: Sync.each(() => faker.number.int({ min: 0, max: 999 })),
  distance: Sync.each(() => faker.number.float({ precision: 0.01, min: 10, max: 9999 })),
})

Then, use that factory inside the parent object:

const parentObjectFactory = Factory.Sync.makeFactory<Machine>({
  displayName: Sync.each(() => faker.internet.displayName()),
  childObject: ChildObjectFactory.build()
})