我正在使用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 的精彩教程都很棒
任何关于带有 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 单元测试 - 包括模拟 - 的教程在 N=29 中提供 http://mvvmcross.wordpress.com/
博客文章也可在 http://blog.fire-development.com/2013/06/29/mvvmcross-enable-unit-testing/
如何人为地设置视图模型,并在测试工具中人为地将消息发布到视图模型?
按照 Stuart 发布的最后一个链接中所述进行设置后,我用来测试 MvxMessenger 的模式是使用 Moq(以及 AutoFixture)创建一个模拟 IMvxMessenger 并注入它:
_mockMvxMessenger = Fixture.Freeze<Mock<IMvxMessenger>> ();
_myViewModel = _fixture.Build<MyViewModel ().OmitAutoProperties().Create ();
以上假设您将 IMvxMessenger 注入到您的 ViewModel 中。
如果您需要检查消息是否已发布,则可以在模拟上断言(验证)
_myViewModel.MyCommand.Execute (null);
_mockMvxMessenger.Verify (m => m.Publish (It.IsAny<MyMvxMessage>()), Times.Once);
如果您需要触发消息,请获取订阅操作并在您喜欢时触发它
在冻结模拟之后但在构建视图模型之前执行此操作:
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));