__tests__/application/TransferenciaServico.test.ts
import { TransferenciaServico } from "../../src/application/TransferenciaServico";
import { MemoriaContaRepositorio } from "../fake/MemoriaContaRepositorio";
import { TransferenciaDTO } from "../../src/application/dto/TransferenciaDTO";
import { Conta } from "../../src/model/Conta";
import { Repositorio } from "../../src/model/contract/Repositorio";
describe("Transferência Serviço", () =>{
test("transferir com sucesso", async () => {
const repositorio: Repositorio<string, Conta> = new MemoriaContaRepositorio();
const contaOrigem: Conta = new Conta("123456", 5000);
const contaDestino: Conta = new Conta("654321", 5000);
repositorio.adicionar(contaOrigem);
repositorio.adicionar(contaDestino);
const transferenciaServico: TransferenciaServico = new TransferenciaServico(repositorio);
const dto: TransferenciaDTO = new TransferenciaDTO("123456", "654321", 100.0);
const recibo: string = await transferenciaServico.transferir(dto);
const contaOrigemRepo = await repositorio.buscar("123456");
const contaDestinoRepo = await repositorio.buscar("654321");
expect(contaOrigemRepo!.saldo).toBe(4900.0);
expect(contaDestinoRepo!.saldo).toBe(5100.0);
expect(recibo.length).toBe(6);
});
});
__tests__/fake/MemoriaContaRepositorio.ts
import { Repositorio } from "../../src/model/contract/Repositorio";
import { Conta } from "../../src/model/Conta";
export class MemoriaContaRepositorio implements Repositorio<string, Conta> {
private _dicionario: Map<string, Conta>;
public constructor(){
this._dicionario = new Map<string, Conta>();
}
public async buscar(numero: string): Promise<Conta | undefined> {
const promise = new Promise<Conta | undefined>((resolve, reject) => {
resolve(this._dicionario.get(numero));
});
return promise;
}
public adicionar(conta: Conta): void {
this._dicionario.set(conta.numero, conta);
}
}
__tests__/model/service/TransferenciaValor.test.ts
import { Conta } from "../../../src/model/Conta";
import { Recibo } from "../../../src/model/Recibo";
import { TransferenciaValor } from "../../../src/model/service/TransferenciaValor";
describe("Transferencia Valor", () => {
test("transferencia de valor entre contas com sucesso", async () => {
const contaOrigem: Conta = new Conta("123456", 1000.0);
const contaDestino: Conta = new Conta("654321", 1000.0);
const transferenciaValor: TransferenciaValor = new TransferenciaValor();
const recibo: Recibo = transferenciaValor.transferir(contaOrigem, contaDestino, 100.0);
expect(contaOrigem.saldo).toBe(900.0);
expect(contaDestino.saldo).toBe(1100.0);
expect(recibo.codigo.length).toBe(6);
});
});
src/application/TransferenciaServico.ts
import { Repositorio } from "../model/contract/Repositorio";
import { Conta } from "../model/Conta";
import { TransferenciaDTO } from "./dto/TransferenciaDTO";
import { TransferenciaValor } from "../model/service/TransferenciaValor";
import { Recibo } from "../model/Recibo";
export class TransferenciaServico {
private _repositorio: Repositorio<string, Conta>;
public constructor(repositorio: Repositorio<string, Conta>){
this._repositorio = repositorio;
}
public async transferir(dto: TransferenciaDTO): Promise<string> {
const contaOrigem = await this._repositorio.buscar(dto.contaOrigem);
const contaDestino = await this._repositorio.buscar(dto.contaDestino);
const transferencia: TransferenciaValor = new TransferenciaValor();
const recibo: Recibo = transferencia.transferir(contaOrigem!, contaDestino!, dto.valor);
this._repositorio.adicionar(contaOrigem!);
this._repositorio.adicionar(contaDestino!);
return recibo.codigo;
}
}
src/error/NegocioErro.ts
export class NegocioErro extends Error {
constructor(message: string) {
super(message);
Object.setPrototypeOf(this, NegocioErro.prototype);
}
}
src/model/Conta.ts
import { NegocioErro } from "../error/NegocioErro";
import { NumeroConta } from "./NumeroConta";
export class Conta {
private _numeroConta: NumeroConta;
private _saldo: number;
public constructor(numero: string, saldo: number) {
this._numeroConta = new NumeroConta(numero);
this._saldo = saldo;
}
public sacar(valor: number): void {
this.validarValor(valor);
if((this.saldo - valor) < 0)
throw new NegocioErro("saldo indisponivel para a operação");
this._saldo -= valor;
}
public depositar(valor: number): void {
this.validarValor(valor);
this._saldo += valor;
}
public get saldo(): number{
return this._saldo;
}
public get numero(): string{
return this._numeroConta.numero;
}
private validarValor(valor: number): void {
if(valor <= 0)
throw new NegocioErro("valor não pode ser igual ou menor que zero");
}
}
src/model/NumeroConta.ts
import { NegocioErro } from "../error/NegocioErro";
export class NumeroConta {
private _numero: string;
public constructor(numero: string) {
if(!this.temSeisDigitos(numero))
throw new NegocioErro("número da conta inválido");
this._numero = numero;
}
public get numero(): string {
return this._numero;
}
private temSeisDigitos(numero: string): boolean {
const regExp: RegExp = /^\d{6}$/;
return regExp.test(numero);
}
}
src/model/contract/Repositorio.ts
export interface Repositorio<I, T>{
buscar(campo: I): Promise<T | undefined>;
adicionar(entidade: T): void;
}