Unit testing 单元测试棱镜导航

Unit testing 单元测试棱镜导航,unit-testing,navigation,prism,Unit Testing,Navigation,Prism,我正在使用Prism和Xamarin表单创建一个应用程序。我想对我的视图模型进行单元测试 我有一个导航到页面的命令。我想断言,在调用该命令后,导航出现在正确的页面上 我想我需要复制文件中的代码 例如,看看这个方法(来自PageNavigationServiceFixture类): 它创建一个导航服务,导航到一个页面,然后断言该页面已更改 下面是我的测试课: [TestClass] public class MenuPrincipalViewModelTests { [TestMethod

我正在使用Prism和Xamarin表单创建一个应用程序。我想对我的视图模型进行单元测试

我有一个导航到页面的命令。我想断言,在调用该命令后,导航出现在正确的页面上

我想我需要复制文件中的代码

例如,看看这个方法(来自PageNavigationServiceFixture类):

它创建一个导航服务,导航到一个页面,然后断言该页面已更改

下面是我的测试课:

[TestClass]
public class MenuPrincipalViewModelTests
{
    [TestMethod]
    public void AProposCommand()
    {
        INavigationService navigationService = new PageNavigationServiceMock(_container, _applicationProvider, _loggerFacade);

        // 1: Here I need to initialize my navigation service to my MasterDetailPage

        MenuPrincipalPageViewModel viewModel = new MenuPrincipalPageViewModel(navigationService);

        viewModel.AProposCommand.Execute();

        // 2: Here I want to assert that the new navigation stack is MenuPrincipalPage/ContenuPage/AProposPage
    }

    PageNavigationContainerMock _container;
    IApplicationProvider _applicationProvider;
    ILoggerFacade _loggerFacade;

    public MenuPrincipalViewModelTests()
    {
        _container = new PageNavigationContainerMock();

        _container.Register("PageMock", typeof(PageMock));

        _container.Register("ContentPage", typeof(ContentPageMock));
        _container.Register(typeof(ContentPageMockViewModel).FullName, typeof(ContentPageMock));

        _container.Register("NavigationPage", typeof(NavigationPageMock));
        _container.Register("NavigationPage-Empty", typeof(NavigationPageEmptyMock));
        _container.Register("NavigationPageWithStack", typeof(NavigationPageWithStackMock));
        _container.Register("NavigationPageWithStackNoMatch", typeof(NavigationPageWithStackNoMatchMock));

        _container.Register("MasterDetailPage", typeof(MasterDetailPageMock));
        _container.Register("MasterDetailPage-Empty", typeof(MasterDetailPageEmptyMock));

        _container.Register("TabbedPage", typeof(TabbedPageMock));
        _container.Register("CarouselPage", typeof(CarouselPageMock));

        _container.Register("MenuPrincipalPage", typeof(MenuPrincipalPage));
        _container.Register("ContenuPage", typeof(ContenuPage));
        _container.Register("ClubHousePage", typeof(ClubHousePage));
        _container.Register("AProposPage", typeof(AProposPage));

        _applicationProvider = new ApplicationProviderMock();
        _loggerFacade = new EmptyLogger();
    }
}
构造函数是从PageNavigationServiceFixture复制的。我现在需要实现AProposCommand测试,我有两个问题(在代码中注明)

如何初始化导航服务模拟以便它复制我的应用程序?有关信息,请参见我的应用程序类:

public partial class App : PrismApplication
{
    public App(IPlatformInitializer initializer = null) : base(initializer) { }

    protected override void OnInitialized()
    {
        InitializeComponent();

        NavigationService.NavigateAsync("MenuPrincipalPage/ContenuPage/ClubHousePage");
    }

    protected override void RegisterTypes()
    {
        Container.RegisterTypeForNavigation<MenuPrincipalPage>();
        Container.RegisterTypeForNavigation<ClubHousePage>();
        Container.RegisterTypeForNavigation<AProposPage>();
        Container.RegisterTypeForNavigation<ContenuPage>();
    }
}
公共部分类应用程序:PrismApplication
{
公共应用程序(IPlatformInitializer initializer=null):基(初始值设定项){}
受保护的覆盖无效OnInitialized()
{
初始化组件();
NavigationService.NavigateAsync(“菜单触诊/内容页/会所页”);
}
受保护的覆盖无效注册表类型()
{
Container.RegisterTypeForNavigation();
Container.RegisterTypeForNavigation();
Container.RegisterTypeForNavigation();
Container.RegisterTypeForNavigation();
}
}
MenuPrincipalPage是一个MasterDetailPage,ContenuPage是一个NavigationPage

我的第二个问题是:如何断言导航堆栈现在是MenuPrincipalPage/ContenuPage/ClubHousePage

非常感谢您的阅读和回答

Julien

您建议的是单元测试Prism,而不是您的代码。对ViewModel进行单元测试是一件好事,但您只需要提供一个模拟,该模拟为您提供了一种验证所需导航字符串/参数是否有效的方法。例如,您的模拟可能看起来像:

public class MockNavigationService : INavigationService
{
    public string LastNavigationString { get; private set; }
    public NavigationParameters LastNavigationParameters { get; private set; }

    public Task NavigateAsync(string name, NavigationParameters parameters, bool? useModalNavigation = null, bool animated = true)
    {
        LastNavigationString = name;
        LastNavigationParameters = parameters;
        return Task.FromResult(0);
    }
}

在我看来,您真正的目标不是运行单元测试,而是通过UITest验证应用程序的导航和用户体验。

为什么需要这么复杂?出于某种原因,您必须测试实际的导航服务吗?否则,只需将模拟传递到视图模型中,执行命令并检查是否使用正确的参数调用了模拟导航服务上的正确方法。这里我要测试的是视图模型,而不是导航。为了创建视图模型,我使用了导航模拟。然后,在调用视图模型方法之后,我检查当前页面是否已正确更改。为了做到这一点,我研究了导航系统。豪金格,你的建议正是我所做的。我的问题是,我不知道如何使用Prism源代码提供的mock来实现这一点。我只是更新了我的问题。我重新组织了测试类的代码,使测试方法位于顶部。这样,更清楚的是导航使用的是模拟,而不是视图模型。使用moq,您只需创建一个新的模拟,将其传递给视图模型,然后调用
验证(x=>x.NavigateAsync(…任何您期望的参数…,Times.one)
如果要测试使用导航的代码,我真的不明白为什么要从prism复制一个用于测试导航的模拟。。
public class MockNavigationService : INavigationService
{
    public string LastNavigationString { get; private set; }
    public NavigationParameters LastNavigationParameters { get; private set; }

    public Task NavigateAsync(string name, NavigationParameters parameters, bool? useModalNavigation = null, bool animated = true)
    {
        LastNavigationString = name;
        LastNavigationParameters = parameters;
        return Task.FromResult(0);
    }
}