Search code examples
c#unit-testingunity-containerprismuwp

Win10 UWP, Prism/Unity and Unit Tests plus Class Libraries, silent failure


Basic layout is currently a simple app. Nothing fancy, I've got Views in the App.Views namespace and my ViewModels in the App.ViewModels namespace. The ViewModels are autowired to the Views through the XAML directive:

xmlns:prismMvvm="using:Prism.Windows.Mvvm"
prismMvvm:ViewModelLocator.AutoWireViewModel="True"

So, basically, this works. Then I wanted to leverage Unity's IoC / DependencyInjection for some unit tests.

The usual way would be to simply add a Windows 10 Unit Test App to the existing app and reference the latter in the Unit Test App.

This will crash upon executing the unit tests because it seems that you may not derive the App class from anything other but Application. I.e. this works:

public sealed partial class App : Application

This does not:

public sealed partial class App : PrismUnityApplication

It's probably also not Prism's fault and something Microsoft has to fix on their end.

Now, the proposed workaround is to simply put whatever you want to unit test into a class library and reference this library from the unit test app. This works for unit testing. It also works for the Models.

My naive approach does not work, however, for the ViewModels. The ViewModel classes are still found under the App.ViewModels namespace, as before, just that they're now in a Class Library. I can access them programmatically in the main app just fine. But upon running the program, the AutoWiring silently fails without an error.

Even when I do something like this, it still does not work:

ViewModelLocationProvider.Register(typeof(MainPage).ToString(), () => new ViewModels.MainPageViewModel());

I'm not that experienced with the technologies involved yet so without an actual error I'm a bit at a loss.

edit: Just to add to the mystery - this code does work, regardless of whether the ViewModel resides in the main app or the class library:

var x = Container.Resolve(typeof(ExamplePageViewModel)) as ExamplePageViewModel;

Solution

  • You are correct, this is a limitation of UWP application testability in general. The testability of UWP apps is imperfect right now. In order to fix the first issue, you need to add the BindableAttribute to your application class:

    [Bindable]
    sealed partial class App : PrismUnityApplication
    {
    
    }
    

    As far as pulling your Views/ViewModels out into separate assemblies, this issue is due to how UWP handles loading types form separate assemblies. None the less, this shouldn't stop you from testing your ViewModels. You can use a regular class library to test your ViewModel logic. You will mock your dependencies. You shouldn't be creating instances of your Views to test your ViewModels. So the ViewModelLocator becomes a non-issue.