tests ddd lib

This commit is contained in:
sbriat 2023-06-28 11:02:55 +02:00
parent ef48e8ae68
commit b12ba842c0
3 changed files with 125 additions and 2 deletions

View File

@ -13,11 +13,11 @@ import { Test, TestingModule } from '@nestjs/testing';
import { Prisma } from '@prisma/client';
import { v4 } from 'uuid';
export interface FakeProps {
interface FakeProps {
name: string;
}
export interface CreateFakeProps {
interface CreateFakeProps {
name: string;
}

View File

@ -0,0 +1,76 @@
import {
AggregateID,
AggregateRoot,
DomainEvent,
DomainEventProps,
} from '@libs/ddd';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { v4 } from 'uuid';
interface FakeProps {
name: string;
}
interface CreateFakeProps {
name: string;
}
class FakeRecordCreatedDomainEvent extends DomainEvent {
readonly name: string;
constructor(props: DomainEventProps<FakeRecordCreatedDomainEvent>) {
super(props);
this.name = props.name;
}
}
class FakeEntity extends AggregateRoot<FakeProps> {
protected readonly _id: AggregateID;
static create = (create: CreateFakeProps): FakeEntity => {
const id = v4();
const props: FakeProps = { ...create };
const fake = new FakeEntity({ id, props });
fake.addEvent(
new FakeRecordCreatedDomainEvent({
aggregateId: id,
name: props.name,
}),
);
return fake;
};
validate(): void {
// not implemented
}
}
const mockLogger = {
debug: jest.fn(),
log: jest.fn(),
error: jest.fn(),
warn: jest.fn(),
};
describe('AggregateRoot Base', () => {
it('should define an aggregate root based object instance', () => {
const fakeInstance = FakeEntity.create({
name: 'someFakeName',
});
expect(fakeInstance).toBeDefined();
expect(fakeInstance.domainEvents.length).toBe(1);
});
it('should publish domain events', async () => {
jest.spyOn(mockLogger, 'debug');
const eventEmitter = new EventEmitter2();
jest.spyOn(eventEmitter, 'emitAsync');
const fakeInstance = FakeEntity.create({
name: 'someFakeName',
});
await fakeInstance.publishEvents(mockLogger, eventEmitter);
expect(mockLogger.debug).toHaveBeenCalledTimes(1);
expect(eventEmitter.emitAsync).toHaveBeenCalledTimes(1);
expect(fakeInstance.domainEvents.length).toBe(0);
});
});

View File

@ -0,0 +1,47 @@
import { Command, CommandProps } from '@libs/ddd';
import { ArgumentNotProvidedException } from '@libs/exceptions';
class FakeCommand extends Command {
readonly name: string;
constructor(props: CommandProps<FakeCommand>) {
super(props);
this.name = props.name;
}
}
class BadFakeCommand extends Command {
constructor(props: CommandProps<BadFakeCommand>) {
super(props);
}
}
describe('Command Base', () => {
it('should define a command based object instance', () => {
const fakeCommand = new FakeCommand({ name: 'fakeName' });
expect(fakeCommand).toBeDefined();
expect(fakeCommand.id.length).toBe(36);
});
it('should define a command based object instance with a provided id', () => {
const fakeCommand = new FakeCommand({ id: 'some-id', name: 'fakeName' });
expect(fakeCommand.id).toBe('some-id');
});
it('should define a command based object instance with metadata', () => {
const fakeCommand = new FakeCommand({
name: 'fakeName',
metadata: {
correlationId: 'some-correlation-id',
causationId: 'some-causation-id',
userId: 'some-user-id',
timestamp: new Date('2023-06-28T05:00:00Z').getTime(),
},
});
expect(fakeCommand.metadata.timestamp).toBe(1687928400000);
});
it('should throw an exception if props are empty', () => {
expect(() => new BadFakeCommand({})).toThrow(ArgumentNotProvidedException);
});
});