私はMVVMパターンの正規版ではありません。これは基本的には初めてのプレーです。WPF MVVM LightユニットのテストViewModels
ビジネス・レイヤーとデータ・レイヤー(通常はサービスまたはEntity Frameworkによって作成されたエンティティを含む)を使用してビューを作成していました(通常のWPF)。
は現在、いくつかいじるの後に私は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>();
}
}
}
ログインの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", passwordBox.SecurePassword, b => Assert.AreEqual(b, false));
}
}
今、私のテストはのViewModel自体ではなく、直接ビジネス層にはありません。
は基本的に私は2つの質問があります。正しい道に
アムIを、あるいは私のパターンの実装に根本的な欠陥があるのでしょうか?
ViewModelをテストするにはどうすればよいですか?
ありがとうございました!しかし、私は探している、あなたはまだコマンドの結果をテストしているか、またはコマンドが正しく実行されただけですか? – YesMan85
@ Rogier21:* "コマンドの結果" *であなたは何を理解していますか?直接的な結果は、ビジネス層への呼び出し(これは上のテストでカバーされています)です。間接的な結果は、ビジネス層のコードが何であれ、どんなものでもあります。そして、それはビジネス層テストでテストする必要があります(私が見る限り、あなたは既に 'DesignUserService'テストでそれを行います)。 –
はい、私はあなたのポイントを参照してください。あなたは2つのテストを受けることになります.1つはビジネスレイヤーのメソッドの適切な結果をテストするため(Loginなど)、もう1つはViewModelからメソッドが正しく呼び出されているかどうかをテストすることですか? – YesMan85