π See DISCLAIMER for legal and usage disclaimers related to this repository.
This demo project will use in upcomming tutorial series for Unit Testing (xUnit), BDD (SpecFlow, xUnit), UI testing (Selenium WebDriver, xUnit) and Database Testing (tSQLt).
- View a list of books
- Add a new book
- Edit or delete a book
A simple ASP.NET MVC (.NET Framework 4.8) application for managing a library of books. This project demonstrates clean layered architecture, separation of concerns, dependency injection, and testability, suitable for BDD (SpecFlow), UI automation (Selenium), xUnit-based unit testing, and database unit testing with tSQLt.
BookLibrary/
βββ BookLibrary.Database/ # SQL Server Database Project (with tSQLt for DB unit tests)
βββ BookLibrary.Data/ # Data access (EF models, DbContext, Repository)
βββ BookLibrary.Business/ # Business logic (Services, business rules)
βββ BookLibrary.Web/ # ASP.NET MVC web UI (Controllers, Views)
βββ BookLibrary.UnitTests/ # Test project (xUnit)
βββ BookLibrary.IntegrationTests/ # Test project (xUnit, SpecFlow)
βββ BookLibrary.UITests/ # Test project (xUnit, Selenium)
βββ BookLibrary.DatabaseTests/ # Test project (tSQLt)
The BookLibrary.Database project is for source-controlling your SQL scripts (tables, procs, initial data, tSQLt tests, migrations), not for database-first modeling. Your application can still use EF Code-First or EF Migrations.
- Database Project: Contains
.sql
files for tables, views, stored procedures, and scripts. - Unit Testing with tSQLt: Contains test classes and test procedures, enabling unit tests at the T-SQL level (e.g., for a
Book
table or ausp_AddBook
stored procedure). - Automated Builds: Allows you to deploy, version, and test the database independently.
- Entities: Defines
Book
with properties (Id
,Title
,Author
). - DbContext:
LibraryContext
manages EF DB connection andDbSet<Book>
. - Repository Pattern:
IBookRepository
abstracts data access;BookRepository
implements CRUD usingLibraryContext
.
- Services:
IBookService
interface andBookService
implementation. - Business Rules: Encapsulates domain logic, e.g., book titles cannot contain the word "Test" (throws exception if violated).
- Dependency: Uses
IBookRepository
for data operations.
- Controllers: e.g.,
BooksController
depends onIBookService
(not direct data access). - Views: Razor views for listing, creating, editing, deleting books.
- Error Handling: Business rule violations are shown as model errors in the UI.
- Unity Container: Configured in
UnityConfig.cs
(Web project).- Maps interfaces to implementations:
IBookRepository
βBookRepository
IBookService
βBookService
- Registers
LibraryContext
- Maps interfaces to implementations:
- Controller Construction: Services injected via constructors, allowing for easy mocking and testing.
- xUnit: For unit testing business, repository, and controller layers.
- SpecFlow: BDD scenarios for features like "Add Book", "List Books".
- Selenium: UI automation for browser-based tests, e.g., verifying business rules in the UI.
- Database (tSQLt): Database unit tests live in the database project and can be run independently or as part of a CI/CD pipeline.
- Separation of Concerns: Data access, business logic, and UI are distinct, reducing coupling.
- Testability: All dependencies are injected; repositories and services can be mocked.
- Maintainability: Business rules are centralized in the business layer.
- Reusability: Business logic is decoupled from UI, so it can be reused in other apps (e.g., APIs).
- Extensibility: New features or rules can be added to the business layer without affecting other parts of the system.
- BDD & Automation Ready: Structure is ideal for SpecFlow (business scenarios) and Selenium (UI tests).
- Database Script Management: Ensures all DB schema and logic changes are tracked and testable.
- User submits 'Add Book' form in the UI.
- BooksController receives the request, calls
IBookService.AddBook
. - BookService checks business rules (e.g., title doesn't contain "Test").
- If invalid, throws exception.
- If valid, calls
IBookRepository.Add
andSave
.
- BookRepository persists the book using
LibraryContext
. - If error, message is displayed in UI; if success, user is redirected to book list.
sequenceDiagram
participant U as User (UI)
participant C as BooksController
participant S as BookService
participant R as BookRepository
participant D as LibraryContext (DB)
participant SQL as BookLibrary.Database (SQL Scripts)
U->>C: Submit Add Book form
C->>S: AddBook(book)
S->>S: Validate business rule (title cannot contain "Test")
alt Valid
S->>R: Add(book)
R->>D: SaveChanges()
D->>SQL: Underlying SQL scripts maintained in BookLibrary.Database
C->>U: Redirect to Book List
else Invalid
S->>C: throw InvalidOperationException
C->>U: Display error message
end
This project is designed so you can demonstrate and teach all major test levels in a modern .NET Framework solution using xUnit.
- Purpose:
- Source-control all DDL/DML scripts (tables, procs, data, migrations)
- Optionally, include tSQLt unit tests for DB logic (e.g., stored procs, constraints)
- Not for database-first modelingβyour EF models still drive schema
Where?
BookLibrary.UnitTests
project.
What to Test?
- Business Layer: Test business rules in
BookService
(e.g., prevent "Test" in book title). - Repository Layer: (optional, with in-memory DB or mocking).
- Controller Logic: Test controller actions using mocks for
IBookService
. - Validation: Edge cases (nulls, invalid data).
Why?
- Fast feedback.
- Pinpoint bugs in isolated units (no DB or UI required).
- Teaches how to use Moq or similar libraries for dependency mocking.
Where?
BookLibrary.IntegrationTests
project (with SpecFlow NuGet).
What to Test?
- Business Scenarios: End-user stories, e.g., "As a librarian, I want to add a book so that it appears in the catalog."
- Integration: End-to-end scenarios, e.g., adding a book and verifying it appears in the list.
- Negative Cases: Try adding a book with "Test" in title and check for error.
Why?
- Closes the gap between requirements and implementation.
- Living documentation for business logic.
- Can drive development (TDD/BDD).
Where?
BookLibrary.UITests
(UI test folder).
What to Test?
- UI Flows: Add, edit, delete book via the browser.
- Validation Messages: Confirm business rules/errors appear in UI.
- Cross-browser: Optionally, Chrome, Firefox, Edge, etc.
Why?
- Ensures entire stack works together.
- Catches regression and integration bugs.
- Mimics real user behavior.
Test Level | Layer Under Test | Dependencies | Tools/Libraries |
---|---|---|---|
DB Unit Test | SQL Schema/Procedures | tSQLt, SQL Server | tSQLt, SSMS/CI/CD |
Unit Test | Business, Controller | Mocked Repositories | xUnit, Moq |
BDD (SpecFlow) | Full Stack | Real DB/Test DB | SpecFlow, xUnit |
UI Test | Full Stack + UI | Real DB, Browser | Selenium WebDriver, xUnit |
-
Database Unit Test (tSQLt):
Show how to write and run database unit tests for entities and stored procedures. -
Unit Test (xUnit):
Start with business/service layer. Show test isolation using mocks. -
SpecFlow (BDD):
Write scenarios in Gherkin, implement step definitions, and show how they connect to real business logic. -
UI Test (Selenium + xUnit):
Automate the browser, show how the UI enforces business rules. -
Integration:
Show how all tests together provide confidence in the application.