繁体   English   中英

单元测试Viewmodel

[英]Unit testing the Viewmodel

我是TDD的新手。 我已经开始在视图模型上创建我需要的属性作为普通的自动属性。

public string Firstname { get; set; }

然后我创建了一个测试

[TestMethod]
[Tag("Property")]
public void FirstNameTest()
{
    ViewModel = new CustomerViewModel();
    ViewModel.PropertyChanged += (s, e) =>
                                     {
                                         Assert.AreEqual("Firstname", e.PropertyName);
                                         Assert.AreEqual("Test", ViewModel.Firstname);
                                     };
    ViewModel.Firstname = "Test";
}

然后我会扩展实际的实现,使测试通过这样:

public string Firstname
{
    get { return _contact.FirstName; }
    set
    {
        if (_contact.FirstName == value)
            return;

        _contact.FirstName = value;

        RaisePropertyChanged(() => Firstname);
    }
}

我遇到的问题是测试仍然传递给Aut属性。 任何提示,如何我可以改善我的过程?

你可以这样做:

    [TestMethod]
    [Tag("Property")]
    public void FirstNameTest()
    {
        bool didFire = false;
        ViewModel = new CustomerViewModel();
        ViewModel.PropertyChanged += (s, e) =>
                                         {
                                             didFire = true;
                                             Assert.AreEqual("Firstname", e.PropertyName);
                                             Assert.AreEqual("Test", ViewModel.Firstname);
                                         };
        ViewModel.Firstname = "Test";
        Assert.IsTrue(didFire);
    }

您可以尝试将测试编写为异步。 考虑这个测试方法:

[TestMethod]
[Asynchronous]
public void TestMethod1()
{
    TestViewModel testViewModel = new TestViewModel();

    bool firstNameChanged = false;

    testViewModel.PropertyChanged +=
        (s, e) =>
            {
                if (e.PropertyName == "FirstName")
                {
                    firstNameChanged = true;
                }
            };

    EnqueueCallback(() => testViewModel.FirstName = "first name");
    EnqueueConditional(() => firstNameChanged == true);
    EnqueueTestComplete();
}

请注意方法顶部的Asynchronous属性。 这里有两个重要的方法:EnqueueCallback和EnqueueTestComplete。 EnqueueCallback会将lambda表达式添加到队列中,测试方法将等待直到执行当前回调。 在这种情况下,我们在ViewModel上订阅PropertyChanged事件,当FirstName属性通知更改时,我们将本地布尔变量设置为true。 然后我们排队两个回调:一个用于设置FirstName属性,另一个用于断言本地布尔变量已更改值。 最后,我们需要添加对EnqueueTestComplete()的调用,以便框架知道测试结束了。

注意:为了获得EnqueueCallback和EnqueueTestComplete,您需要在测试类上继承SilverlightTest。 您还需要导入Microsoft.Silverlight.Testing以获取Asynchronous属性。 它应该看起来像这样:

using Microsoft.Silverlight.Testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Foo.Example.Test
{
    [TestClass]
    public class Tests : SilverlightTest
    {

        // ... tests go here
    }
}

您需要进行另一个实际断言您的PropertyChanged甚至会触发的测试。

当您进行该测试时,您的自动属性应该失败,因为该事件永远不会触发。

以下是如何在Moq中执行此操作的示例

测试应该失败,除非它正在测试的行为已经实现。

为了在我上次尝试中测试属性更改通知,我创建了一个帮助程序类 ,帮助我编写这样的测试(它在NUnit中)

[Test]
public void NotifiesChangeIn_TogglePauseTooltip()
{
   var listener = new PropertyChangeListener(_mainViewModel);

   _mainViewModel.TogglePauseCommand.Execute(null);

   Assert.That(listener.HasReceivedChangeNotificationFor("TogglePauseTooltip"));
}

这是我过去做过的事情(我使用的是NUnit所以它可能有点不同):

[Test]
public void ShouldNotifyListenersWhenFirstNameChanges()
{
    var propertiesChanged = new List<string>();

    ViewModel = new CustomerViewModel();
    ViewModel.PropertyChanged += (s, e) => propertiesChanged.Add(e.PropertyName);

    ViewModel.Firstname = "Test";

    Assert.Contains("Firstname", propertiesChanged);      
    Assert.AreEqual("Test", ViewModel.Firstname);  
}

如果它不是Firstname ,那么能够调试和解决改变的东西有很好的副作用。 当您从其他字段计算多个字段时非常方便。 您还可以在代码中查看行为的其他方面:

[Test]
public void ShouldNotNotifyListenersWhenPropertiesAreNotChanged()
{
    var propertiesChanged = new List<string>();

    ViewModel = new CustomerViewModel();
    ViewModel.Firstname = "Test";

    ViewModel.PropertyChanged += (s, e) => propertiesChanged.Add(e.PropertyName);

    ViewModel.Firstname = "Test";

    Assert.AreEqual(0, propertiesChanged.Count); 
}

也许这个代码有更多的背景未被揭示,但我所看到的似乎不必要地复杂化。 为什么还要加入RaisePropertyChanged事件呢? 设置后只需检查属性。

[TestMethod]
[Tag("Property")]
public void FirstNameTest()
{
    var expected = "John";
    var sut = new CustomerViewModel();

    sut.Firstname = expected;

    Assert.AreEqual(expected, sut.Firstname);
}

这也将测试变成了真正的单元测试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM