AgentStack
SKILL verified MIT Self-run

Maui Unit Testing

skill-davidortinau-maui-skills-maui-unit-testing · by davidortinau

>

No reviews yet
0 installs
5 views
0.0% view→install

Install

$ agentstack add skill-davidortinau-maui-skills-maui-unit-testing

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Maui Unit Testing? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

.NET MAUI Unit Testing — Gotchas & Best Practices

For project templates, xUnit examples, ViewModel test patterns, and CLI commands, see references/unit-testing-api.md.

⚠️ TFM Trap: Don't Use Platform-Specific TFMs


net9.0-ios

net9.0;net10.0

⚠️ OutputType Trap: App Project as Test Dependency

If your test project references the app project, the app tries to build as Exe for the test TFM — this fails. Add a conditional OutputType:


Exe

  Library

  Exe

Common Mistakes

❌ Using Static MAUI APIs in ViewModels

ViewModels that directly call static MAUI APIs are untestable:

// ❌ Untestable — Shell.Current requires a running MAUI app
public async Task GoToDetail(int id)
    => await Shell.Current.GoToAsync($"detail?id={id}");

// ✅ Inject an interface — fully testable
public class MyViewModel(INavigationService nav)
{
    public async Task GoToDetail(int id)
        => await nav.GoToAsync($"detail?id={id}");
}

Static APIs to wrap behind interfaces:

  • Shell.CurrentINavigationService
  • Application.Current → avoid entirely
  • SecureStorage.DefaultISecureStorage
  • Connectivity.CurrentIConnectivity

❌ Asserting on UI Bindings Instead of ViewModel State

// ❌ Testing the binding — fragile, needs a running UI
Assert.Equal("Hello", label.Text);

// ✅ Testing the ViewModel — fast, no platform dependency
Assert.Equal("Hello", viewModel.Title);
Assert.True(viewModel.SaveCommand.CanExecute(null));

Mocking Strategy for MAUI Services

| MAUI Service | Mock Strategy | |-------------|---------------| | ISecureStorage | Mock — stub GetAsync/SetAsync | | IPreferences | Mock — stub Get/Set/Remove | | IConnectivity | Mock — return NetworkAccess | | IGeolocation | Mock — return fixed Location | | IFilePicker | Mock — return FileResult | | IMediaPicker | Mock — return FileResult | | Shell navigation | Abstract behind INavigationService | | IDispatcher | Stub Dispatch to invoke action synchronously |

Architecture: Interface-First for Testability

Define service interfaces so ViewModels have zero MAUI platform dependencies:

// ✅ These make your entire ViewModel layer testable
public interface INavigationService
{
    Task GoToAsync(string route);
    Task GoBackAsync();
}

public interface IDialogService
{
    Task ConfirmAsync(string title, string message);
}

Register implementations in MauiProgram.cs; inject interfaces into ViewModels.

Tips

  • No Application.Current or Shell.Current in ViewModels — wrap in injectable services
  • Use ObservableCollection and [ObservableProperty] (MVVM Toolkit) for testable state
  • Assert on ViewModel properties and CanExecute, not UI bindings
  • Use TaskCompletionSource to test async waiting flows
  • Run dotnet test in CI to catch regressions early
  • On-device tests: Use xunit.runner.devices for real platform APIs (sensors, camera, Bluetooth)

Checklist

  • [ ] Test project targets plain net9.0/net10.0 (not platform-specific TFMs)
  • [ ] App project has conditional OutputType for test TFM
  • [ ] All MAUI static APIs wrapped behind injectable interfaces
  • [ ] ViewModels tested via properties and commands, not UI bindings
  • [ ] IDispatcher mocked to invoke synchronously in tests
  • [ ] dotnet test runs green in CI

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.