Test code that uses the plugin
Your view models and services depend on INearbyConnectivity, so fake that interface and test them
on the desktop. You need no device and no emulator.
Put your view models and services in a net10.0 class library, and reference that library from
both the app and the tests. A MAUI app targets net10.0-android and net10.0-ios, which a desktop
test project cannot reference.
Target net10.0 from the test project
The package also has a plain net10.0 target, so a test project can reference it. That target
exists for compilation, not for use at run time. On it, CheckAvailabilityAsync reports
NearbyAvailability.Unsupported and every start method throws NearbyException.
Fake the interfaces
INearbyConnectivity, INearbyAdvertiser, and INearbyDiscoverer are public interfaces, so a
mocking library can fake them. The examples use NSubstitute.
var nearby = Substitute.For<INearbyConnectivity>();
To test a failure path, return the real exception type:
nearby.Discoverer.StartAsync(Arg.Any<CancellationToken>())
.Returns(Task.FromException(new NearbyException("Bluetooth is off.")));
The real session raises its events on a thread-pool thread. A fake raises them on the test's thread. Code that dispatches to the UI thread works with both.
Build devices for the fake to report
NearbyDevice has a public constructor for tests. Build a device with the status that your test
needs, and raise DeviceChanged with it.
var ana = new NearbyDevice("a1", new NearbyPresence { DisplayName = "Ana" })
{
Status = NearbyDeviceStatus.Connected,
};
nearby.Devices.Returns([ana]);
nearby.DeviceChanged += Raise.Event<EventHandler<NearbyDeviceChange>>(
nearby, new NearbyDeviceChange(NearbyDeviceChangeAction.Added, ana));
A device built this way belongs to no session, so ConnectAsync and DisconnectAsync throw
InvalidOperationException.
NearbyConnection and NearbyConnectionRequest are sealed, and their constructors are internal. A
test cannot create them, and a mocking library cannot fake them. To test code that sends or
accepts, put that call behind a method that your view model owns. Then fake that method.
Register the plugin in a bare host
AddNearbyConnectivity also exists on IServiceCollection, for a host without a MauiAppBuilder.
It works where nobody called AddLogging. It also
registers a TimeProvider if the host registered none. It validates the options, so an invalid
ServiceId throws at the registration call. The first registration wins: a second call registers
nothing, and its options are ignored.
var services = new ServiceCollection();
services.AddNearbyConnectivity(o => o.ServiceId = "tests");
Next
- Samples for two apps that you can run.
- CONTRIBUTING.md if you contribute to the plugin itself.