# Unit Testing

FlexBase is designed from the ground up to be testable. The framework provides clear separation of concerns, making it easy to write focused unit tests for each layer of your application.

## Why FlexBase Testing is Different

Traditional enterprise applications often have tightly coupled components that are difficult to test in isolation. FlexBase solves this through:

| Challenge                  | FlexBase Solution                                          |
| -------------------------- | ---------------------------------------------------------- |
| Tightly coupled components | Clear layer separation (Domain, PreBus, Handlers, Queries) |
| Database dependencies      | InMemory EF Core with `InMemoryRepoFactory`                |
| Service locator patterns   | Dependency injection with `FlexHostMock`                   |
| Complex setup requirements | Reusable fixtures and seed data                            |
| Hard to mock dependencies  | Interface-based design (`IRepoFactory`, `IFlexHost`)       |

## Testing Layers

FlexBase applications have four primary testing layers:

```
┌─────────────────────────────────────────────────────────────┐
│                    Test Layer Overview                       │
├─────────────────────────────────────────────────────────────┤
│  1. Domain Model Tests     - Business logic, no DB needed   │
│  2. PreBus Validation Tests - Rules with InMemory database  │
│  3. Query Tests            - Read operations, verify fetches │
│  4. Handler Tests          - Command orchestration (optional)│
└─────────────────────────────────────────────────────────────┘
```

### 1. Domain Model Tests

Test pure business logic without any database. Uses `FlexHostMock` to get domain model instances.

**What to test:** CreateX, UpdateX, DeleteX methods, property mapping, validation guards.

### 2. PreBus Validation Tests

Test validation plugins (business rules) with InMemory EF Core. Each plugin is tested in isolation.

**What to test:** Existence checks (CategoryExists, ProductTypeExists), uniqueness (SlugUnique), value validation.

### 3. Query Tests

Test read operations against InMemory database with seed data.

**What to test:** Fetch operations, null handling for missing records, property mapping from entities to DTOs.

### 4. Handler Tests (Optional)

For complex orchestration scenarios. Often the combination of domain model + validation tests provides sufficient coverage.

## Quick Start

See the [xUnit Guide](https://docs.flexbase.in/solution-structure/getting-started/unit-testing/xunit) for detailed setup instructions and code examples.

## Key Components

| Component                        | Purpose                                  | NuGet Package                    |
| -------------------------------- | ---------------------------------------- | -------------------------------- |
| `FlexHostMock`                   | Test-friendly `IFlexHost` implementation | Sumeru.Flex.Core                 |
| `InMemoryRepoFactory`            | InMemory EF Core repository factory      | Your `.Testing.InMemory` project |
| `ApplicationEFInMemoryDbContext` | InMemory DbContext with seed data        | Your `.Testing.InMemory` project |

## Recommended Test Project Structure

```
YourApp/
├── Domain/
│   └── YourApp.DomainModels.Tests/
│       ├── Fixtures/
│       │   └── FlexHostMockFixture.cs
│       └── Product/
│           └── ProductDomainModelTests.cs
├── DomainHandler/
│   ├── YourApp.PreBus.Tests/
│   │   ├── Fixtures/
│   │   └── Products/Validations/
│   │       ├── SlugUniqueValidationTests.cs
│   │       └── CategoryExistsValidationTests.cs
│   ├── YourApp.Queries.Tests/
│   │   ├── Fixtures/
│   │   │   └── QueryTestFixture.cs
│   │   └── Products/
│   │       └── GetProductByIdTests.cs
│   └── YourApp.Handlers.Tests/
│       └── (Optional - for complex scenarios)
└── Infrastructure/
    └── YourApp.Testing.InMemory/
        ├── InMemoryRepoFactory.cs
        ├── ApplicationEFInMemoryDbContext.cs
        └── SeedData/
            ├── ProductType_SeedData.cs
            ├── Category_SeedData.cs
            └── Product_SeedData.cs
```

## Best Practices

1. **Use unique database names** - Each test class should use `Guid.NewGuid()` in the database name to ensure isolation
2. **Leverage seed data** - Create realistic seed data once, reference it in all tests
3. **Use xUnit collection fixtures** - Share expensive setup (like FlexHostMock) across test classes
4. **Test one thing per test** - Each test should verify a single behavior
5. **Use FluentAssertions** - Makes assertions readable and provides helpful error messages

## Next Steps

* [xUnit Testing Guide](https://docs.flexbase.in/solution-structure/getting-started/unit-testing/xunit) - Complete setup and examples
* [ECommerz Sample Tests](https://github.com/sumeru-flexbase/flexbase-docs/blob/main/samples/ecommerz/testing/README.md) - Real-world examples
