4

我正在使用 Xamarin Studio 开始使用 MvvmCross 进行 TDD。我试图首先测试发布到视图模型的消息的效果,以便仅在收到适当的消息时执行逻辑。

我将 Stuart 的一些优秀教程拼凑在一起,从而成功地将位置数据传播到视图模型,然后在 IOS 视图上更新一些文本控件、地图标记等。

但在进一步深入之前,我想使用 TDD 进行编码。如何人为地设置视图模型并在我的测试工具中人为地向其发布消息?:

public class MyViewModel : MvxViewModel
{
    private readonly MvxSubscriptionToken _token;

    public MyViewModel(ILocationService service, IMvxMessenger messenger)
    {
        //weak reference
        _token = messenger.Subscribe<LocationMessage>(OnLocationMessage);
    }

    private void OnLocationMessage(LocationMessage locationMessage)
    {
        Lat = locationMessage.Lat;
        Lng = locationMessage.Lng;
        // Console.WriteLine("on loc msg {0:0.0000}, {1:0.0000}", Lat, Lng);
    }

    private double _lng;
    public double Lng
    {
        get { return _lng; }
        set
        {
            _lng = value;
            RaisePropertyChanged(() => Lng);
        }
    }

    private double _lat;
    public double Lat
    {
        get { return _lat; }
        set
        {
            _lat = value;
            RaisePropertyChanged(() => Lat);
        }
    }
}


[TestFixture()]
public class LocTest
{
    [Test()]
    public void LocationMessageIsRecieved()
    {
        // im using nsubstitute to mock with
        var locService = Substitute.For<ILocationService>();  
        var msgr = Substitute.For<IMvxMessenger>();
        var vm = new Map2ViewModel(locService, msgr);

        var locMsg = new LocationMessage(this, 1F, 2F);
        msgr.Publish(locMsg);

        var lat = vm.Lat;
        Assert.AreEqual(2F, lat);  // says lat is 0.0  and nunit doesnt let me debug the tests :(
    }
}

任何关于 MvvmCross 的 TDD 很棒的教程都会很棒

4

2 回答 2

8

任何关于 MvvmCross 的 TDD 很棒的教程都会很棒

Greg Shackles 在 Evolve 的演讲是一个很好的起点 - http://xamarin.com/evolve/2013#session-7wb0etd3r8

他的 CodeCamp 示例包含一组极好的单元测试示例 - http://www.gregshackles.com/2013/09/nyc-code-camp-8-mobile-apps/通向https://github.com/gshackles/ NycCodeCamp8/tree/master/CodeCamp.Core/tests/CodeCamp.Core.Tests/ViewModelTests

有关 MvvmCross 单元测试的教程(包括模拟)可在http://mvvmcross.wordpress.com/上的 N=29 中找到

博客文章也可在http://blog.fire-development.com/2013/06/29/mvvmcross-enable-unit-testing/上找到

于 2013-11-04T08:48:31.827 回答
4

如何人为地设置视图模型并在我的测试工具中人为地向其发布消息?:

按照 Stuart 发布的最后一个链接中所述进行设置后,我用来测试 MvxMessenger 的模式是使用Moq(连同AutoFixture)创建一个模拟 IMvxMessenger 并注入它:

_mockMvxMessenger = Fixture.Freeze<Mock<IMvxMessenger>> ();
_myViewModel = _fixture.Build<MyViewModel ().OmitAutoProperties().Create ();

以上假设您将 IMvxMessenger 注入您的 ViewModel。

如果您需要检查消息是否已发布,您可以在 mock 上断言(验证)

_myViewModel.MyCommand.Execute (null);
_mockMvxMessenger.Verify (m => m.Publish (It.IsAny<MyMvxMessage>()), Times.Once);

如果您需要触发消息,则抓住订阅 Action 并在您喜欢时触发它

在冻结 Mock 之后但在构建 ViewModel 之前执行此操作:

private Action<MyMvxMessage> _callbackAction; // class scope var
_mockMvxMessenger.Setup (n => n.Subscribe<MyMvxMessage> (It.IsAny<Action<MyMvxMessage>> (), It.IsAny<MvxReference>(), It.IsAny<string>())).Callback<Action<MyMvxMessage>, MvxReference, string> ((action,mvxref,tag) => _callbackAction = action);

然后在您的测试中,您只需调用即可“触发消息”

_callbackAction(new MyMvxMessage(this));
于 2015-11-25T09:37:05.830 回答