如何为moq中的属性赋值?
我有一个类的方法,返回一个User
types的对象
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
是一个域对象。 注意setter的Id
属性为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是受保护的,因为它是由数据库生成的。
testing项目
在我的testing项目中,我有一个Fake存储库和一个方法Store
来保存/更新对象:
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
我有public override MembershipUser CreateUser
方法调用GetUser
来创build一个User
。
这样,我所要做的就是模拟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”创build一个用户时,用户将返回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();
这个方法将准备模拟的所有属性,以便能够logging分配的值,并在以后重放(即充当不动产)。
您还可以使用SetProperty()
方法来设置单个属性,以便logging传入的值。
另一种方法是:
var mockUser = Mock.Of<User>( m => m.Name == "wahtever" && m.Email == "some@example.com"); return mockUser;
我想你错过了嘲笑的目的。 嘲笑用来模拟你正在testing的类的依赖关系:
被测系统(SUT)应该被隔离testing(即与其他单元分开)。 否则,依赖项中的错误会导致SUTtesting失败。 你也不应该为嘲笑写testing。 这不会给你什么,因为嘲笑不是生产代码。 嘲笑不会在您的应用程序中执行。
所以,只有在testing某个依赖于它的单元时,才应该模拟CustomMembershipProvider
(顺便说一下,最好创build一些像ICustomMembershipProvider
接口ICustomMembershipProvider
抽象方法)。
或者,如果您正在编写CustomMembershipProvider
类的testing,那么它不应该被嘲笑 – 只应该嘲笑这个提供者的依赖关系。