Tôi không thường xuyên với mẫu MVVM và đây là lần đầu tiên tôi chơi với nó.WPF MVVM Kiểm tra đơn vị ánh sáng ViewModels
Điều tôi thường làm (WPF "bình thường"), đã tạo Chế độ xem với lớp Doanh nghiệp và có thể là trình chứa dữ liệu (thường chứa các thực thể của tôi được tạo bởi dịch vụ hoặc Khung thực thể).
Bây giờ sau khi một số toying Tôi tạo ra một khuôn mẫu chuẩn từ MVVM Light và đã làm điều này:
Locator:
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>();
}
}
}
Đăng nhập 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");
}
});
}
}
Binding và các lệnh làm việc tốt do đó không có câu hỏi. Lớp mockup kinh doanh cho thiết kế và thời gian thử nghiệm:
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 là lớp tĩnh gọi điện đến cơ sở dữ liệu (Entity Framework).
Bây giờ tôi có thử nghiệm của tôi:
[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));
}
}
Bây giờ thử nghiệm của tôi không xuất hiện trên ViewModel bản thân nhưng trực tiếp đến lớp kinh doanh.
Về cơ bản tôi có 2 câu hỏi:
Am tôi trên con đường đúng đắn, hoặc là có thiếu sót cơ bản trong việc thực hiện mô hình của tôi?
Tôi làm cách nào để kiểm tra ViewModel của mình?
Cảm ơn câu trả lời của bạn! Nhưng tôi đang tìm kiếm, bạn vẫn đang thử nghiệm kết quả của lệnh hay chỉ khi lệnh được thực thi đúng cách? – YesMan85
@ Rogier21: Bạn hiểu gì về * "kết quả của lệnh" *? Kết quả trực tiếp sẽ là một cuộc gọi đến lớp kinh doanh (được bao phủ với kiểm tra ở trên) - kết quả gián tiếp sẽ là bất kỳ mã lớp kinh doanh nào. Và điều đó nên được kiểm tra với các bài kiểm tra lớp nghiệp vụ (và theo như tôi thấy, bạn đã làm điều đó với thử nghiệm 'DesignUserService'). –
Có, tôi thấy quan điểm của bạn. Bạn có nghĩa là bạn sẽ nhận được 2 bài kiểm tra: 1 để kiểm tra kết quả phù hợp của phương thức trong lớp nghiệp vụ (ví dụ Đăng nhập), và 1 bài kiểm tra để kiểm tra xem phương thức có được gọi chính xác từ ViewModel không? – YesMan85