I am using xUnit to unit test my MAUI app.
I am testing my ViewModel class. The issue that I have is that a segment of code uses:
if (MainThread.IsMainThread)
{
DoSomething();
}
else
{
MainThread.BeginInvokeOnMainThread(DoSomething);
}
And xUnit is not able to use this code.
How would you go around that, ideally without having to specify special conditional symbols just for unit tests to run ? Is there a way to set up xUnit that I have missed ?
Note: here is the exception raised when such code is reached by code inside a xUnit project:
Microsoft.Maui.ApplicationModel.NotImplementedInReferenceAssemblyException: 'This functionality is not implemented in the portable version of this assembly. You should reference the NuGet package from your main application project in order to reference the platform-specific implementation.'
Usually, when you have dependencies that you can't control, either coming from the framework itself or from a 3rd party, you're not supposed to test them at all. If what you're attempting to test the DoSomething()
method, a simple solution would be to introduce an interface and a wrapper class for the MainThread
:
interface IMainThread
{
bool IsMainThread {get;}
void BeginInvokeOnMainThread(Action action); // not sure about this signrature
}
class MainThreadWrapper : IMainThread
{
public bool IsMainThread
=> MainThread.IsMainThread;
public void BeginInvokeOnMainThread(Action action)
=> MainThread.BeginInvokeOnMainThread(action);
}
Then you inject that implementation to your testable class in the application, so your code looks like this:
if (_mainThread.IsMainThread)
{
DoSomething();
}
else
{
_mainThread.BeginInvokeOnMainThread(DoSomething);
}
(_mainThread
being an instance implementing the IMainThread
interface)
and in your tests you inject a mock or a fake for that interface.