タイプUser
のオブジェクトを返すメソッドを持つクラスがあります
public class CustomMembershipProvider : MembershipProvider
{
public virtual User GetUser(string username, string password, string email, bool isApproved)
{
return new User()
{
Name = username
,Password = EncodePassword(password)
,Email = email
,Status = (isApproved ? UsuarioStatusEnum.Ativo : UsuarioStatusEnum.ConfirmacaoPendente)
// ...
};
}
// ..
}
User
はドメインオブジェクトです。 Id
プロパティに注意してくださいsetter as protected:
public class User : IAuditable, IUser
{
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual string Email { get; set; }
public virtual UsuarioStatusEnum Status { get; set; }
public virtual string Password { get; set; }
}
Idはデータベースによって生成されるため保護されています。
私のテストプロジェクトには、オブジェクトを保存/更新するメソッドStore
を持つFakeリポジトリがあります。
public void Store(T obj)
{
if (obj.Id > 0)
_context[obj.Id] = obj;
else
{
var generateId = _context.Values.Any() ? _context.Values.Max(p => p.Id) + 1 : 1;
var stubUser = Mock.Get<T>(obj); // In test, will always mock
stubUser.Setup(s => s.Id).Returns(generateId);
_context.Add(generateId, stubUser.Object);
}
}
CustomMembershipProvider
には、GetUser
を呼び出してUser
を作成するpublic override MembershipUser CreateUser
メソッドがあります。
この方法では、リポジトリがGetUser
を生成できるように、Id
メソッドをモックするだけです。
var membershipMoq = new Mock<CustomMembershipProvider>();
membershipMoq.CallBase = true;
membershipMoq
.Setup(p => p.GetUser(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
.Returns<string, string, string, bool>( (username, password, email, isAproved) => {
var moqUser = new Mock<User>();
moqUser.Object.Name = username;
moqUser.Object.Password = password;
moqUser.Object.Email = email;
moqUser.Object.Status = (isAproved ? UsuarioStatusEnum.Ativo : UsuarioStatusEnum.ConfirmacaoPendente);
return moqUser.Object;
});
_membershipProvider = membershipMoq.Object;
理論的にはすべてが正しいです。 CreateUser
が 'GetUser'を呼び出してユーザーを作成すると、ユーザーはMockを入力して返します。
[TestMethod]
public void CreateUser_deve_criar_usuario_no_repositorio()
{
// Act
MembershipCreateStatus status;
var usr = _membershipProvider.CreateUser(
_fixture.Create<string>(),
_fixture.Create<string>(),
_fixture.Create<string>(),
null, null, true, null,
out status);
// usr should have name, email password filled. But not!
// Assert
status.Should().Be(MembershipCreateStatus.Success);
}
問題は、電子メール、名前、パスワードが空(デフォルト値)であることです!
模擬ユーザーを準備する方法が問題です。
moqUser.Object.Name = username;
モックを適切にセットアップしない限り、名前は設定されません。プロパティに値を割り当てる前にこれを試してください:
moqUser.SetupAllProperties();
このメソッドは、割り当てられた値を記録できるようにモックのすべてのプロパティを準備し、後で再生します(つまり、実際のプロパティとして機能します)。
SetupProperty()メソッドを使用して、渡された値を記録できるように個々のプロパティを設定することもできます。
別のアプローチは次のとおりです。
var mockUser = Mock.Of<User>( m =>
m.Name == "whatever" &&
m.Email == "[email protected]");
return mockUser;
あなたはモッキングの目的を逃していると思います。テストするクラスの依存関係を模擬するために使用されるモック:
テスト対象システム(SUT)は、分離してテストする必要があります(つまり、他のユニットから分離する)。そうしないと、依存関係のエラーにより、SUTテストが失敗します。また、モックのテストを作成しないでください。モックは本番用のコードではないため、それでは何も得られません。モックはアプリケーションで実行されません。
したがって、CustomMembershipProvider
をモックする必要があるのは、それに依存するユニットをテストする場合のみです(ただし、依存するインターフェイスICustomMembershipProvider
のような抽象化を作成することをお勧めします)。
または、CustomMembershipProvider
クラスのテストを作成する場合は、モックを作成しないでください。このプロバイダーの依存関係のみをモックする必要があります。