@binary-stars/bs-uuid-generator
v0.3.0
Published
UUID generator for dependency injection, clean code and testing
Downloads
42
Maintainers
Readme
README
When you create objects with auto-generated IDs then it's cumbersome to test them for equality
because the generated attribute value is (duh!) auto-generated.
This library enables you to inject the UUID generator via the strategy pattern and
choose the appropriate implementation for testing as opposed to production.
As for the production-ready implmentation, you can either use UuidGeneratorUuidv4Impl
(which uses the "uuid" npm package)
or use any other tool via UuidGeneratorDelegatingImpl
.
Brought to you by binary stars GmbH, written in TypeScript and tested with 100% coverage.
Installation
npm i --save @binary-stars/bs-uuid-generator
How to use
In your production code:
// this type is just a tweak, you can use whatever
type Entity<T> = T & {
id: string
}
type User = {
name: string
}
// In this example I'm injecting the uuidGenerator into the Data Access Object.
// I think this is a nice design choice but you can have the uuid generated whereever you want instead.
class MyUserDaoWithAutoId {
constructor(private uuidGenerator: UuidGenerator) {}
put(user: User): Entity<User> {
return {
...user,
id: this.uuidGenerator.create(),
}
}
}
In your production initialization/dependency injection/factory code:
import UuidGeneratorUuidv4Impl from '@binary-stars/bs-uuid-generator/dist/UuidGeneratorUuidv4Impl'
const dao = new MyUserDaoWithAutoId(new UuidGeneratorUuidv4Impl())
/* ALTERNATIVELY, use any other way to create a UUID Generator */
import UuidGeneratorDelegatingImpl from '@binary-stars/bs-uuid-generator/dist/UuidGeneratorDelegatingImpl'
const genSimpleRandom = () => {
let out = ''
for (let i = 0; i < 32; i++) {
const rand = Math.floor(Math.random() * 16)
if (rand < 10) {
out += `${rand}`
} else {
out += String.fromCharCode(rand + 87)
}
}
return out
}
const dao = new MyUserDaoWithAutoId(
new UuidGeneratorDelegatingImpl(genSimpleRandom),
)
In your tests
import UuidGenerator, {
isUuid,
UuidGeneratorDelegatingImpl,
} from '@binary-stars/bs-uuid-generator/dist/UuidGenerator'
import {
UuidGeneratorFixedImpl,
UuidGeneratorSequenceImpl,
} from '@binary-stars/bs-uuid-generator/dist/UuidGenerators'
let dao: MyUserDaoWithAutoId
describe('Demo', () => {
test("Production Mode: in production we want to use a ROBUST implementation, so let's use the uuid4 lib", () => {
// given
dao = new MyUserDaoWithAutoId(new UuidGeneratorUuidv4Impl())
// when
const actual = dao.put({name: 'Joey'})
// then
expect(actual.name).toEqual('Joey')
expect(actual.id).toBeTruthy()
expect(isUuid(actual.id)).toBe(true)
})
test('... but we could use any other implementation just as well', () => {
// given
const genSimpleRandom = () => {
let out = ''
for (let i = 0; i < 32; i++) {
const rand = Math.floor(Math.random() * 16)
if (rand < 10) {
out += `${rand}`
} else {
out += String.fromCharCode(rand + 87)
}
}
return out
}
dao = new MyUserDaoWithAutoId(
new UuidGeneratorDelegatingImpl(genSimpleRandom),
)
// when
const actual = dao.put({name: 'Joey'})
// then
expect(actual.name).toEqual('Joey')
expect(actual.id).toBeTruthy()
expect(isUuid(actual.id)).toBe(true)
})
test('Testing Mode: in testing we want to use a test friendly implementation, e.g. one that always yields the same value', () => {
// given
dao = new MyUserDaoWithAutoId(UuidGeneratorFixedImpl.ONE)
// when
let actual = dao.put({name: 'Joey'})
// then
expect(actual).toEqual({
name: 'Joey',
id: '00000000-0000-0000-0000-000000000001',
})
// the same fact as above:
expect(actual.id).toEqual(UuidGeneratorFixedImpl.ONE.create())
// when 2
actual = dao.put({name: 'CJ'})
// then 2
expect(actual).toEqual({
name: 'CJ',
id: '00000000-0000-0000-0000-000000000001',
})
// the same fact as above:
expect(actual.id).toEqual(UuidGeneratorFixedImpl.ONE.create())
})
test('Testing Mode: ... or an implementation that works like a sequence', () => {
// given
const uuidGenerator = new UuidGeneratorSequenceImpl()
dao = new MyUserDaoWithAutoId(uuidGenerator)
// when
let actual = dao.put({name: 'Joey'})
// then
expect(actual).toEqual({
name: 'Joey',
id: UuidGeneratorSequenceImpl.get(1),
})
// the same fact as above:
expect(actual.id).toEqual('00000000-0000-0000-0000-000000000001')
// when 2
actual = dao.put({name: 'CJ'})
// then 2
expect(actual).toEqual({
name: 'CJ',
id: UuidGeneratorSequenceImpl.get(2),
})
// the same fact as above:
expect(actual.id).toEqual('00000000-0000-0000-0000-000000000002')
})
})
Contribution guidelines
- 100% code coverage
- run
npm run review
to check style, eslint, run tests and check coverage
About us
- binary stars GmbH, Hausinger Str. 8, 40764 Langenfeld, Germany
- #clean-code #clean-architecture #tdd #xp #agile
- We offer a CTO2Go for your software projects & products + developers, QA engineers and agile project managers
- Wanna know how we achieve 100% coverage EVERY TIME? Contact us about our training & consulting services.
- Our open source projects: https://www.binary-stars.eu/en/open-source-projects/
Version History
- 0.3.0
- Remove dashes if dashes = false
- Bump to 0.3 to indicate 'more major' change
- 0.2.4
- Improve build process
- Fix FormattingDecorator as it wasn't really a decorator before
- 0.2.3 (finally public)
- improve readme and demo testss
- 0.2.2 (private)
- fix README & CI script
- 0.2.1 (private)
- fix README & CI script
- 0.2.0 (private)
- create README
- 0.1.0 (private)
- first working release