3
votes

I want to test a Xamarin view model with xUnit. When the code is build using command line on Mac, the following error are show:

/usr/local/share/dotnet/sdk/3.1.300/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(283,5): error NETSDK1073: The FrameworkReference 'Microsoft.WindowsDesktop.App.WPF' was not recognized

If <GenerateErrorForMissingTargetingPacks>false</GenerateErrorForMissingTargetingPacks> is used on .csproj, the project compiles, but the following error are reported when I try to run the test.

System.BadImageFormatException : Duplicate type with name 'App.<>PropertyChangedEventArgs'

The view model are show below (part of the class). Fody and PropertyChanged.Fody are used to automate the implementation of INotifyPropertyChanged.

[AddINotifyPropertyChangedInterface]
public class ListaTarefasViewModel : ViewModelBase, IHandleViewAppearing, IHandleViewDisappearing
{

    public ListaTarefasViewModel(
        ITarefaService tarefaService,
        ITarefaRepository tarefaRepository,
        ITarefaRetornoItensRepository tarefaRetornoItensRepository,
        INotificationService notificationService,
        IUsuarioRepository usuarioRepository,
        IProdutoRepository produtoRepository)
    {
        this.tarefaService = tarefaService;
        this.tarefaRepository = tarefaRepository;
        this.notificationService = notificationService;
        this.usuarioRepository = usuarioRepository;
        this.tarefaRetornoItensRepository = tarefaRetornoItensRepository;
        this.produtoRepository = produtoRepository;
    }

    // ...
}

The test class:

public class ListaTarefasViewModelTest : IDisposable
{
    private readonly Mock<ListaTarefasViewModel> listaTarefasViewModelMock;

    public ListaTarefasViewModelTest()
    {
        listaTarefasViewModelMock = new Mock<ListaTarefasViewModel>();
    }

    public void Dispose()
    {
    }

    [Fact]
    public async Task ShouldConfigureTipoTarefaWhenInitializeAsync()
    {
        object tipoTarefa = TipoTarefaEnum.Inventario;
        await listaTarefasViewModelMock.Object.InitializeAsync(tipoTarefa);
        Assert.Equal(TipoTarefaEnum.Inventario, listaTarefasViewModelMock.Object.TipoTarefa);
    }
}
1
Hi Rony! I just finished adding Unit Tests to my GitTrends app and wanted to share them as an example of how to write Unit Tests for ViewModels for a Xamarin.Forms app: github.com/brminnick/GitTrends/tree/master/GitTrends.UnitTests/…Brandon Minnick

1 Answers

4
votes

Build and Execution Errors

The error

/usr/local/share/dotnet/sdk/3.1.300/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(283,5): error NETSDK1073: The FrameworkReference 'Microsoft.WindowsDesktop.App.WPF' was not recognized

was caused by the use of the package Rg.Plugins.Popup, because it depends of WPF through Xamarin.Forms (Xamarin.Forms.Platform.WPF). This can be resolved by using <PrivateAssets>all</PrivateAssets> on the .csproj file.
Example:

<PackageReference Include="Rg.Plugins.Popup" Version="2.0.0.3">
    <PrivateAssets>all</PrivateAssets>
</PackageReference>

Reference about the .csproj file configuration: Package references (PackageReference) in project files

The error

System.BadImageFormatException : Duplicate type with name 'App.<>PropertyChangedEventArgs'

was solved by cleaning the entire solution or the shared project, but this is needed to be made before any test. This appears to be caused by Fody or PropertyChanged.Fody.
That are issues related to the this error, but none was resolved by now: issue on PropertyChanged.Fody repository and issue on MarcStan / resource-embedder repository.

Unit Test

Finally, the code uses Autofac and the test was made with xUnit. The class was tested with the mock getting all the dependencies from another mocks.

var tarefaService = Mock.Of<ITarefaService>();
var tarefaRepository = Mock.Of<ITarefaRepository>();
// ...
var mockListaTarefasViewModel = new Mock<ListaTarefasViewModel>(
    MockBehavior.Loose,
    tarefaService,
    tarefaRepository,
    // ..
);
mockListaTarefasViewModel
    .Setup(/* .. */)
    .Verifiable();
mockListaTarefasViewModel.Verify();