我曾经做过的(“正常”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?
现在可以问,当您已经对基础业务逻辑进行测试时,测试命令的目的是什么?目的是验证业务逻辑被调用并具有正确的参数.
如何做这样的测试?使用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所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)