我不是MVVM模式的常规人员,这基本上是我第一次玩它。我曾经做过的事情(“普通”WPF),是通过业务层和数据层(通常包含由服务或实体框架创建的实体)创建我的视图。WPF MVVM光单元测试ViewModels
现在有些玩弄后,我创建了从MVVM光一个标准模板,这样做:
定位:
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>();
}
}
}
登录视图模型:
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是一个静态类,这使得调用数据库(实体框架)。
现在我有我的测试:
[TestClass]
public class Login
{
[TestMethod]
public void IncorrectUsernameCorrectPassword()
{
IUserService userService = new DesignUserService();
PasswordBox passwordBox = new PasswordBox
{
Password = "password"
};
userService.Login("nonexistingusername", passwordBox.SecurePassword, b => Assert.AreEqual(b, false));
}
}
现在我的测试是不是在视图模型本身,而是直接到业务层。
基本上我有2个问题:
我在正确的道路上,还是有我的模式实现一个根本的缺陷?
我该如何测试我的ViewModel?
感谢您的回答!但我在看,你还在测试命令的结果还是只是命令执行正确? – YesMan85
@ Rogier21:你通过*“命令的结果”*了解了什么?直接结果将是对业务层的调用(覆盖上面的测试) - 间接结果将是业务层代码所做的任何事情。这应该通过业务层测试进行测试(并且据我所知,您已经使用'DesignUserService'测试来完成这项工作)。 –
是的,我明白你的观点。你的意思是你会得到2个测试:1测试在业务层中的方法的正确结果(例如登录),1测试以测试方法是否从ViewModel正确调用? – YesMan85