Skip to content
Development
Skill

/dunitx-testing

Unit testing patterns with DUnitX for Delphi — fixtures, mocking, integration tests

From plugin
delphi-spec-kit
5218 skills1 command
Install
$ npx -y skills add delphicleancode/delphi-spec-kit --skill dunitx-testing --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/dunitx-testing

Context preview

The summary Claude sees to decide when to auto-load this skill.

Unit testing patterns with DUnitX for Delphi — fixtures, mocking, integration tests

SKILL.md

dunitx-testing.SKILL.md
name: "DUnitX Testing Patterns"
description: "Unit testing patterns with DUnitX for Delphi — fixtures, mocking, integration tests"

DUnitX Testing Patterns — Skill

Use this skill when creating or organizing unit tests in Delphi projects.

When to Use

  • When creating tests for new features
  • When applying TDD (Test-Driven Development)
  • When creating database integration tests
  • When refactoring existing tests

Test Project Structure

tests/
├── MeuApp.Tests.dpr                 ← Projeto de testes
├── Domain/
│   ├── MeuApp.Tests.Customer.Entity.pas
│   └── MeuApp.Tests.Order.Entity.pas
├── Application/
│   ├── MeuApp.Tests.Customer.Service.pas
│   └── MeuApp.Tests.Order.Service.pas
├── Infrastructure/
│   └── MeuApp.Tests.Customer.Repository.pas
└── Helpers/
    ├── MeuApp.Tests.Helpers.Database.pas
    └── MeuApp.Tests.Helpers.Mocks.pas

Basic Test Fixture

unit MeuApp.Tests.Customer.Service;

interface

uses
  DUnitX.TestFramework,
  MeuApp.Domain.Customer.Entity,
  MeuApp.Domain.Customer.Repository.Intf,
  MeuApp.Application.Customer.Service;

type
  [TestFixture]
  TCustomerServiceTest = class
  private
    FService: TCustomerService;
    FMockRepo: ICustomerRepository;
  public
    [Setup]
    procedure Setup;

    [TearDown]
    procedure TearDown;

    [Test]
    procedure CreateCustomer_WithValidData_ShouldSucceed;

    [Test]
    procedure CreateCustomer_WithEmptyName_ShouldRaiseException;

    [Test]
    procedure CreateCustomer_WithDuplicateCpf_ShouldRaiseException;

    [Test]
    procedure GetById_WithExistingId_ShouldReturnCustomer;

    [Test]
    procedure GetById_WithInvalidId_ShouldRaiseNotFoundException;
  end;

implementation

uses
  System.SysUtils;

{ TCustomerServiceTest }

procedure TCustomerServiceTest.Setup;
begin
  FMockRepo := TMemoryCustomerRepository.Create;
  FService := TCustomerService.Create(FMockRepo);
end;

procedure TCustomerServiceTest.TearDown;
begin
  FService.Free;
  //FMockRepo is interface — released automatically
end;

[Test]
procedure TCustomerServiceTest.CreateCustomer_WithValidData_ShouldSucceed;
begin
  Assert.WillNotRaiseAny(
    procedure
    begin
      FService.CreateCustomer('João Silva', '12345678901', 'joao@email.com');
    end
  );
end;

[Test]
procedure TCustomerServiceTest.CreateCustomer_WithEmptyName_ShouldRaiseException;
begin
  Assert.WillRaise(
    procedure
    begin
      FService.CreateCustomer('', '12345678901', 'joao@email.com');
    end,
    EValidationException
  );
end;

[Test]
procedure TCustomerServiceTest.CreateCustomer_WithDuplicateCpf_ShouldRaiseException;
begin
  FService.CreateCustomer('João', '12345678901', 'joao@email.com');

  Assert.WillRaise(
    procedure
    begin
      FService.CreateCustomer('Maria', '12345678901', 'maria@email.com');
    end,
    EBusinessRuleException
  );
end;

[Test]
procedure TCustomerServiceTest.GetById_WithExistingId_ShouldReturnCustomer;
var
  LCustomer: TCustomer;
begin
  FService.CreateCustomer('João', '12345678901', 'joao@email.com');

  LCustomer := FService.GetById(1);
  try
    Assert.IsNotNull(LCustomer);
    Assert.AreEqual('João', LCustomer.Name);
  finally
    LCustomer.Free;
  end;
end;

[Test]
procedure TCustomerServiceTest.GetById_WithInvalidId_ShouldRaiseNotFoundException;
begin
  Assert.WillRaise(
    procedure
    begin
      FService.GetById(999);
    end,
    EEntityNotFoundException
  );
end;

initialization
  TDUnitX.RegisterTestFixture(TCustomerServiceTest);

end.

Mock Repository (in memory)

unit MeuApp.Tests.Helpers.Mocks;

interface

uses
  System.SysUtils,
  System.Generics.Collections,
  MeuApp.Domain.Customer.Entity,
  MeuApp.Domain.Customer.Repository.Intf;

type
  TMemoryCustomerRepository = class(TInterfacedObject, ICustomerRepository)
  private
    FItems: TObjectList<TCustomer>;
    FNextId: Integer;
  public
    constructor Create;
    destructor Destroy; override;

    function FindById(AId: Integer): TCustomer;
    function FindAll: TObjectList<TCustomer>;
    function FindByCpf(const ACpf: string): TCustomer;
    function Exists(AId: Integer): Boolean;
    procedure Insert(ACustomer: TCustomer);
    procedure Update(ACustomer: TCustomer);
    procedure Delete(AId: Integer);
  end;

implementation

constructor TMemoryCustomerRepository.Create;
begin
  inherited Create;
  FItems := TObjectList<TCustomer>.Create(False);
  FNextId := 1;
end;

destructor TMemoryCustomerRepository.Destroy;
begin
  FItems.Free;
  inherited;
end;

procedure TMemoryCustomerRepository.Insert(ACustomer: TCustomer);
begin
  ACustomer.Id := FNextId;
  Inc(FNextId);
  FItems.Add(ACustomer);
end;

//... other methods follow the same pattern

Test Naming Conventions

MethodName_Scenario_ExpectedBehavior

| Example | Meaning | |---------|-------------| | `CreateCustomer_WithValidData_ShouldSucceed` | Happy scenery | | `CreateCustomer_WithEmptyName_ShouldRaiseException` | Validation | | `GetById_WithInvalidId_ShouldRaiseNotFoundException` | Not found | | `Delete_WhenItemHasDependencies_ShouldRaiseException` | Business rule |

DUnitX Common Assertions

//equality
Assert.AreEqual(Expected, Actual);
Assert.AreEqual('João', LCustomer.Name);

//Nullity
Assert.IsNotNull(LCustomer);
Assert.IsNull(LResult);

//Booleanos
Assert.IsTrue(LCustomer.IsActive);
Assert.IsFalse(LOrder.IsCancelled);

//Exceptions
Assert.WillRaise(AnonProc, EValidationException);
Assert.WillNotRaiseAny(AnonProc);

// Contagem
Assert.AreEqual(3, LList.Count);

Integration Test with SQLite in Memory

[TestFixture]
TCustomerRepositoryIntegrationTest = class
private
  FConnection: TFDConnection;
  FRepository: ICustomerRepository;
public
  [Setup]
  procedure Setup;

  [TearDown]
  procedure TearDown;
end;

procedure TCustomerRepositoryIntegrationTest.Setup;
begin
  FConnection := TFDConnection.Create(nil);
  FConnection.DriverName := 'SQLite';
  FConnection.Params.Database := ':memory:';
  FConnection.Connected := T
Read more
Ships withdelphi-spec-kit

An opinionated ecosystem of rules, skills and steerings to elevate Delphi development to state-of-the-art with Artificial Intelligence.

Get the whole plugin
Stats
52
Stars
14
Forks
Maintained
Maintenance
MIT
License
5mo ago
Last commit
6mo ago
Created

Repo: delphicleancode/delphi-spec-kit

Other skills on delphi-spec-kit.