c# – WPF MVVM Light单元测试ViewModels
我不是一个常规的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本身,而是直接到业务层. 基本上我有两个问题: 我在正确的道路上,还是我的模式实现有根本的缺陷? 解决方法
您的视图模型有一个值得测试的相关代码,这是Login方法.鉴于它是私有的,它应该通过LoginCommand进行测试.
现在可以问,当您已经对基础业务逻辑进行测试时,测试命令的目的是什么?目的是验证业务逻辑被调用并具有正确的参数. 如何做这样的测试?使用mock. FakeItEasy示例: var userServiceFake = A.Fake<IUserService>(); var testedViewModel = new LoginViewModel(userServiceFake); // prepare data for test var passwordBox = new PasswordBox { Password = "password" }; testedViewModel.UserName = "TestUser"; // execute test testedViewModel.LoginCommand.Execute(passwordBox); // verify A.CallTo(() => userServiceFake.Login( "TestUser",A<Action<bool>>.Ignored) ).MustHaveHappened(); 这样您可以验证该命令是否按预期调用业务层.请注意,Action< bool>在匹配参数时被忽略 – 很难匹配Action< T>和Func< T>通常不值得. 几个注释: >您可能需要重新考虑在视图模型中有消息框代码(这应该属于视图,视图模型应该请求或通知视图来显示弹出窗口).这样做也可以通过测试视图模型(例如,不需要忽略该Action参数) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |