Updated June 2026Test-Driven Development with .NET MAUI and Blazor Hybrid
Class Duration
35 hours of live training delivered over 5 days.
Student Prerequisites
- Professional C# programming experience
- Working knowledge of Blazor and Razor components
- Basic HTML and CSS
- Familiarity with Git
- No prior mobile or testing experience required
Target Audience
Blazor and web developers who want to learn MAUI Blazor Hybrid the test-first way. This course covers the same full curriculum as our Build Cross-Platform Apps with .NET MAUI and Blazor Hybrid course - BlazorWebView, shared UI across native and web, platform integration, data, and deployment - but every feature is built test-first with bUnit at the center. Ideal for teams sharing one Razor component library across native apps and the web, where a regression ships to every platform at once, and for organizations that require automated test coverage in their delivery pipeline.
Description
This is the complete Build Cross-Platform Apps with .NET MAUI and Blazor Hybrid curriculum, taught test-first. Students learn the same .NET 10 material (BlazorWebView, the Blazor Hybrid and Web App solution template, shared Razor class libraries, platform integration, offline data, services, and store deployment) but every component and every feature begins with a failing test. Shared UI multiplies the value of every test: when one Razor component library ships to iOS, Android, Windows, Mac, and the web, a single well-written test protects five platforms, and a single regression breaks them all. The course moves from red-green-refactor discipline and the hybrid testability architecture into component TDD with bUnit at the center: rendering, parameters, events, state, per-target render logic, routing, and forms all driven from failing tests. Data and the hybrid seams follow: SQLite repositories, offline sync conflict cases, in-process test servers, faked MSAL, and JS interop and HybridWebView messaging verified as contracts. The final day completes the production picture with Playwright and Appium end-to-end automation, CI/CD pipelines, coverage and mutation testing, and AI-assisted test generation inside the TDD loop.
Learning Outcomes
- Practice red-green-refactor fluently and organize xUnit test suites that stay fast and maintainable.
- Architect hybrid apps for testability from day one: logic in services and components, platform access behind interfaces, DI as the testing seam.
- Drive Razor components test-first with bUnit: rendering, parameters, EventCallbacks, two-way binding, cascading values, lifecycle, and async state.
- Place the Blazor Hybrid and Web App solution template under test, verifying shared Razor class libraries and per-target render logic across native and web configurations.
- Test routing, navigation, forms and validation, and state management (including state across the hybrid boundary) without launching the app.
- Mock platform services with permission flows as test cases, and apply TDD to local data and services: SQLite repositories, offline sync conflicts, in-process test servers, and faked MSAL.
- Test JS interop boundaries with a faked IJSRuntime, verify HybridWebView messaging contracts, and include accessibility checks in automated tests.
- Automate end-to-end tests with Playwright for the web target and Appium for the native shell, and build CI pipelines with coverage and mutation testing as honesty checks and AI-assisted test generation inside the TDD loop.
Training Materials
Comprehensive courseware is distributed online at the start of class. All students receive a downloadable MP4 recording of the training.
Software Requirements
.NET 10 SDK, Visual Studio 2026 (Windows) or VS Code with the .NET MAUI extension (Windows or Mac), Android SDK with an emulator, Appium, Playwright, and Git. A Mac with Xcode is required only for the iOS labs; all other labs run on Windows or Mac.
Training Topics
TDD Foundations
- Red-green-refactor: the discipline and the payoff
- Test organization with xUnit: fixtures, theories, and naming
- Test tooling in Visual Studio 2026 and VS Code with the .NET MAUI extension
- The test pyramid for shared-UI hybrid apps
- Why shared components raise the stakes - and the value - of every test
Architecting Hybrid Apps for Testability
- The hybrid model through a testing lens: Razor components in a BlazorWebView, .NET running natively
- The single-project model, MauiProgram, and DI as the seam for testing
- Logic in services and components, not host pages
- Platform services behind interfaces; humble objects at the WebView and platform boundaries
- BlazorWebView internals: what you can test in-process and what needs a device
Component TDD with bUnit
- Driving components from failing tests: render, assert, refactor
- Parameters, EventCallbacks, and two-way binding under test
- Cascading values, layouts, and DI dependencies in component tests
- Component state, lifecycle, and async rendering
- Templated components and RenderFragments under test
- Markup assertions that don't break on every refactor
The Shared-UI Solution Template Under Test
- The Blazor Hybrid and Web App template: one component library, five targets
- Razor class libraries structured for test coverage
- Service registration per host: testing against the shared interfaces
- Keeping web and native targets honest with shared test suites
- Where target-specific code hides - and how tests flush it out
Per-Target Render Logic, Verified
- Render modes on the web target vs. always-interactive native hosting
- Testing platform- and form-factor-conditional rendering
- Device detection behind fakeable abstractions
- One component, multiple configurations: parameterized tests across targets
- Preventing target-specific leakage with architecture tests
CSS and Markup Contracts
- CSS isolation in shared components: what tests can and cannot verify
- Semantic markup as the testable contract: classes, roles, and structure
- Asserting on meaningful markup, ignoring cosmetic churn
- Dark mode and theme-dependent class logic under test
- Where automated tests stop and visual review begins
Routing and Navigation Under Test
- Blazor routing inside a native app, tested with bUnit
- Layouts and navigation state under test
- Deep links and back-button behavior as test cases
- Mixing Blazor navigation with native navigation: testing the boundary
- NavigationManager fakes and assertions
- EditForm and form models driven from failing tests
- Data annotations and custom validators under unit test
- Validation messages and submission flows asserted with bUnit
- Async validation and debouncing as test cases
- Form behavior contracts shared across native and web targets
State Management Test-First
- State containers driven from failing tests
- DI lifetimes in the hybrid host: testing scoped state correctly
- Native events updating Razor UI: the hybrid boundary under test
- Suspend/resume persistence as test cases
- Choosing state patterns by their testability
- Isolation with NSubstitute: platform services injected into components
- Geolocation, sensors, connectivity, and share behind fakes
- Permission flows under test: granted, denied, and degraded paths on Android 16 and iOS 26
- Faking time, connectivity, and environmental state
- Avoiding over-mocking: testing behavior, not implementation
- MediaPicker behind an interface: capture and selection flows as test cases
- .NET 10 multi-select and compression: verifying media-handling logic without a camera
- Displaying captured media in components: bUnit assertions on media state
- Failure paths: cancellation, denied permissions, and storage errors as tests
Maps and Location Under Test
- Location logic test-first: distance, proximity, and geofencing rules
- Faking geolocation and geocoding: accuracy, timeouts, and unavailable scenarios
- Map components: testing the .NET side of JS map library integrations
- Offline behavior for location-aware features as test cases
TDD for Local Data
- SQLite repositories test-first
- In-memory and on-disk test strategies
- Migrations under test
- Preferences and SecureStorage behind testable abstractions
- Repository contracts shared across native and web targets
Offline Sync: Conflict Cases as Test Cases
- Offline-first design driven by tests: queued writes and replay
- Conflict detection and resolution strategies, each as a test case
- Connectivity transitions: offline, flaky, and restored networks under test
- Sync state machines verified exhaustively
Remote Services and Auth Under Test
- Service-layer tests with real HTTP via in-process test servers
- Resilience behavior under test: retries, timeouts, and circuit breakers
- Authentication flows with faked MSAL; token storage contracts
- Auth state in components: bUnit tests for signed-in and signed-out rendering
JS Interop and HybridWebView Contracts
- Faking IJSRuntime: testing JS interop call contracts
- .NET-to-JS and JS-to-.NET boundaries under test
- HybridWebView messaging: bidirectional contracts as test cases
- Message serialization, versioning, and error paths
- Keeping interop thin so the tests stay meaningful
Accessibility and Localization in Tests
- Asserting roles, labels, and semantic structure with bUnit
- Accessibility checks in Playwright runs
- Localization under test: resource coverage and culture-aware formatting
- Right-to-left rendering as a test configuration
End-to-End Automation
- Playwright against the web target: fast, reliable browser E2E
- Appium against the native shell on Android 16 and iOS 26: selectors, waits, and stability
- Sharing E2E scenarios across targets
- What belongs in E2E tests - and what does not
CI/CD for Tested Hybrid Apps
- Per-commit pipelines: bUnit and integration suites
- Platform builds with E2E smoke tests on a cadence
- Emulator strategies and device farms in CI
- Test results as release gates
- Telemetry in test and production: Aspire service defaults and OpenTelemetry
Coverage, Mutation, and AI-Assisted Testing
- Coverage reporting: what it tells you and what it hides
- Mutation testing as the honesty check on your suite
- Generating bUnit and integration tests with AI assistants - within the TDD loop
- Reviewing AI-generated tests for real assertions
- Coverage-gap analysis with AI tools