c# – WPF MVVM Light单元测试ViewModels

c# – WPF MVVM Light单元测试ViewModels,第1张

概述我不是一个常规的MVVM模式,这基本上是我第一次玩它. 我曾经做过的(“正常”WPF)正在创建一个业务层和数据层(通常包含由一个服务或实体框架创建的实体)的视图. 现在经过一段折磨,我创建了一个MVVM Light的标准模板,并做到这一点: 定位: public class ViewModelLocator{ static ViewModelLocator() { 我不是一个常规的MVVM模式,这基本上是我第一次玩它.

我曾经做过的(“正常”WPF)正在创建一个业务层和数据层(通常包含由一个服务或实体框架创建的实体)的视图.

现在经过一段折磨,我创建了一个MVVM light的标准模板,并做到这一点:

定位:

public class viewmodelLocator{    static viewmodelLocator()    {        ServiceLocator.SetLocatorProvIDer(() => SimpleIoc.Default);        if (viewmodelBase.IsInDesignmodeStatic)        {            SimpleIoc.Default.Register<IUserService,DesignUserService>();        }        else        {            SimpleIoc.Default.Register<IUserService,IUserService>();        }        SimpleIoc.Default.Register<Loginviewmodel>();    }    public Loginviewmodel Login    {        get        {            return ServiceLocator.Current.GetInstance<Loginviewmodel>();        }    }}

登录viewmodel:

public class Loginviewmodel : viewmodelBase{    private Readonly IUserService _userService;    public RelayCommand<Object> LoginCommand    {        get        {            return new RelayCommand<Object>(Login);        }    }    private string _username;    public String Username    {        get { return _username; }        set        {            if (value == _username)                return;            _username = value;            RaisePropertyChanged("Username");        }    }    /// <summary>    /// Initializes a new instance of the Loginviewmodel class.    /// </summary>    public Loginviewmodel(IUserService userService)    {        _userService = userService;        _closing = true;    }    private voID Login(Object passwordBoxObject)    {        PasswordBox passwordBox = passwordBoxObject as PasswordBox;        if (passwordBox == null)            throw new Exception("PasswordBox is null");        _userService.Login(Username,passwordBox.SecurePassword,result =>        {            if (!result)            {                MessageBox.Show("Wrong username or password");            }        });    }}

绑定和命令工作正常,所以没有问题.商业模型课设计考试时间:

public class DesignUserService : IUserService{    private Readonly User _testUser;    private Readonly IList<User> _users;    public voID Login(String username,securestring password,Action<Boolean> callback)    {        var user = _users.FirstOrDefault(u => u.Username.Tolower() == username.Tolower());        if (user == null)        {            callback(false);            return;        }        String rawPassword = Security.ComputeHashString(password,user.Salt);        if (rawPassword != user.Password)        {            callback(false);            return;        }        callback(true);    }    public DesignUserService()    {        _testUser = new User        {            Username = "testuser",Password = "123123",Salt = "123123"        };        _users = new List<User>        {            _testUser        };    }}

UserData是一个静态类,它调用数据库(Entity Framework).

现在我有我的考试:

[TestClass]public class Login{    [TestMethod]    public voID IncorrectUsernameCorrectPassword()    {        IUserService userService = new DesignUserService();        PasswordBox passwordBox = new PasswordBox        {            Password = "password"        };        userService.Login("nonexistingusername",b => Assert.AreEqual(b,false));    }}

现在我的测试不是在viewmodel本身,而是直接到业务层.

基本上我有两个问题:

我在正确的道路上,还是我的模式实现有根本的缺陷?
>如何测试我的viewmodel?

解决方法 您的视图模型有一个值得测试的相关代码,这是Login方法.鉴于它是私有的,它应该通过LoginCommand进行测试.

现在可以问,当您已经对基础业务逻辑进行测试时,测试命令的目的是什么?目的是验证业务逻辑被调用并具有正确的参数.

如何做这样的测试?使用mock. FakeItEasy示例:

var userServiceFake = A.Fake<IUserService>();var testedviewmodel = new Loginviewmodel(userServiceFake);// prepare data for testvar passwordBox = new PasswordBox { Password = "password" };testedviewmodel.Username = "TestUser";// execute testtestedviewmodel.LoginCommand.Execute(passwordBox);// verifyA.CallTo(() => userServiceFake.Login(    "TestUser",A<Action<bool>>.Ignored)).MustHaveHappened();

这样您可以验证该命令是否按预期调用业务层.请注意,Action< bool>在匹配参数时被忽略 – 很难匹配Action< T>和Func< T>通常不值得.

几个注释:

>您可能需要重新考虑在视图模型中有消息框代码(这应该属于视图,视图模型应该请求或通知视图来显示d出窗口).这样做也可以通过测试视图模型(例如,不需要忽略该Action参数)
>有些人测试INotifyPropertyChanged属性(在您的情况下为Username) – 当属性值更改时会引发该事件.由于这是很多样板代码,因此建议使用工具/ library自动化此过程.>你确实想要有两组测试,一个用于视图模型(如上面的例子),另一个用于底层业务逻辑(原始测试).在MVVM中,虚拟机是一种额外的层,似乎没有什么用处 – 但这就是整体而言 – 在这里没有业务逻辑,而是重点关注数据重新排列/准备视图层.

总结

以上是内存溢出为你收集整理的c# – WPF MVVM Light单元测试ViewModels全部内容,希望文章能够帮你解决c# – WPF MVVM Light单元测试ViewModels所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1262479.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存