2015-06-08 30 views
0

當我的命令需要使用類型爲整數的CommandParameter時,如何爲MvvmCross MvxCommand編寫NUnit測試。如何使用NUnit測試MvvmCross MvxCommand <int>

testListViewModel.EditCommand.Execute(null); 

這是不是一個選項,因爲我有這個ViewModel。如果傳遞參數,CanExecute會繼續。

public class TestListViewModel : MvxViewModel 
{ 
    private readonly ITestService _testService; 
    private readonly IDialogService _dialogService; 
    public TestListViewModel(ITestService testService, IDialogService dialogService) 
    { 
     _testService = testService; 
     _dialogService = dialogService; 
    } 

    public MvxCommand<int> EditCommand { get { return new MvxCommand<int>(Edit, id => id > 0); } }  

    private void Edit(int asTestID) { ShowViewModel<TestViewModel>(new { asTestID }); } 
} 

我使用NUnit +最小起訂量+ Cirrious.MvvmCross.Test.Core引用在我的測試項目,並有這樣的結構。

public class MockDispatcher : MvxMainThreadDispatcher, IMvxViewDispatcher 
{ 
    public readonly List<MvxViewModelRequest> Requests = new List<MvxViewModelRequest>(); 
    public readonly List<MvxPresentationHint> Hints = new List<MvxPresentationHint>(); 
    public bool RequestMainThreadAction(Action action) 
    { 
     action(); 
     return true; 
    } 

    public bool ShowViewModel(MvxViewModelRequest request) 
    { 
     Requests.Add(request); 
     return true; 
    } 

    public bool ChangePresentation(MvxPresentationHint hint) 
    { 
     Hints.Add(hint); 
     return true; 
    } 
} 

[TestFixture] 
class TestListViewModelTest : MvxIoCSupportingTest 
{ 
    [Test] 
    public void TestListViewModel_OnEdit_ShowTestViewModel() 
    { 
     //Arrange 
     base.ClearAll(); 

     var mockDispatcher = new MockDispatcher(); 
     Ioc.RegisterSingleton<IMvxViewDispatcher>(mockDispatcher); 
     Ioc.RegisterSingleton<IMvxMainThreadDispatcher>(mockDispatcher); 

     var mockDialogService = new Mock<IDialogService>(); 
     var mockTestService = new Mock<ITestService>(); 

     var testListViewModel = new TestListViewModel(mockTestService.Object, mockDialogService.Object); 

     //Act 
     testListViewModel.EditCommand.Execute(2); //this line is failing 

     //Assert 
     Assert.AreEqual(1, mockDispatcher.Requests.Count); 
     var request = mockDispatcher.Requests[0]; 
     Assert.AreEqual(typeof(TestViewModel), request.ViewModelType); 
     Assert.AreEqual((2).ToString(), request.ParameterValues["asTestID"]); 
    } 
} 

當我運行測試它拋出MvxIoCResolveException這個調用堆棧。我試圖調試它,並且我的代碼在MvxNavigatingObject.ShowViewModel()上的字面失敗,其中參數是一個對象,並嘗試調用parameterValuesObject.ToSimplePropertyDictionary()
在靜態函數ToSimplePropertyDictionary(此對象輸入)propertyInfos枚舉爲空,所以它不能調用的foreach(在propertyInfos變種的PropertyInfo)

調用堆棧,我從運行測試得到的是:

Cirrious.CrossCore.Exceptions.MvxIoCResolveException : Failed to resolve type Cirrious.MvvmCross.Platform.IMvxStringToTypeParser 
    at Cirrious.CrossCore.IoC.MvxSimpleIoCContainer.Resolve(Type t) 
    at Cirrious.CrossCore.IoC.MvxSimpleIoCContainer.Resolve() 
    at Cirrious.MvvmCross.MvxSingletonCache.get_Parser() 
    at Cirrious.MvvmCross.Platform.MvxSimplePropertyDictionaryExtensionMethods.<ToSimplePropertyDictionary>b__7(PropertyInfo property) 
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 
    at Cirrious.MvvmCross.Platform.MvxSimplePropertyDictionaryExtensionMethods.ToSimplePropertyDictionary(Object input) 
    at Cirrious.MvvmCross.ViewModels.MvxNavigatingObject.ShowViewModel(Object parameterValuesObject, IMvxBundle presentationBundle, MvxRequestedBy requestedBy) 
    at App.Core.ViewModels.TestListViewModel.Edit(Int32 asTestID) in TestListViewModel.cs: line 37 
    at App.Tests.Test.TestListViewModelTest.TestListViewModel_OnEdit_ShowTestViewModel() in TestListViewModelTest.cs: line 97 

任何幫助,將不勝感激!

回答

0

當您使用參數調用ShowViewModel時,有幾種不同的方法可以做到這一點。這決定了MvvmCross如何調用您的Init方法。

  • 個別簡單類型參數
  • 與簡單類型屬性
  • 如InitFromBundle()與IMvxBundle參數的單個類型化參數對象 - 這最後風味總是通過IMvxViewModel接口支持。

您正在使用匿名類型調用ShowViewModel,但沒有屬性名稱。這些屬性名稱必須與Init方法中的參數名稱匹配。

因此,不是這樣的:

private void Edit(int asTestID) { ShowViewModel<TestViewModel>(new { asTestID }); } 

這樣做:

// simply-Typed parameters 
private void Edit(int asTestID) { ShowViewModel<TestViewModel>(asTestID); } 

或者這樣:

// a single Typed parameter object with simply-Typed properties 
private void Edit(int asTestID) { ShowViewModel<TestViewModel>(new { ID = asTestID }); } 

https://github.com/MvvmCross/MvvmCross/wiki/View-Model-Lifecycle#2-init

+0

對不起,但我不知道如何處理Init()中的第一個代碼片段。第二個代碼段與我的類似。 它與以下內容相同:private void Edit(int asTestID){ShowViewModel (new {asTestID = asTestID}); }' –

+0

如果您在匿名類型中包含屬性名稱,它應該可以工作。你還在犯錯嗎? – Kiliman

+0

是的,我仍然無法進行測試。 –