C# 如何在最小起订量中为属性赋值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16816551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to assign values to properties in moq?
提问by ridermansb
I have a class with a method that returns an object of type User
我有一个带有返回类型对象的方法的类 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)
// ...
};
}
// ..
}
Useris a domain object. Note the Idproperty with setter as protected:
User是域对象。请注意setter 为 protected的Id属性:
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 is protected because it is generated by the database.
Id 是受保护的,因为它是由数据库生成的。
Test project
测试项目
In my Test project I have a Fake repository with a method Storeto save/update the object:
在我的测试项目中,我有一个 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);
}
}
In CustomMembershipProviderI have public override MembershipUser CreateUsermethod that calls the GetUserto create a User.
This way, all I have to do is mock the GetUsermethod so that the repository can generate the Id
在CustomMembershipProvider我有public override MembershipUser CreateUser调用 的方法GetUser来创建一个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;
Problem
问题
In theory everything is correct. When CreateUsercall 'GetUser' to create a user, the user will return Mock filled;
理论上一切都是正确的。当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);
}
The problem is that Email, Name, Password are empty (with default values)!
问题是电子邮件、名称、密码为空(使用默认值)!


采纳答案by Sunny Milenov
The way you prepare the mocked user is the problem.
您准备模拟用户的方式是问题所在。
moqUser.Object.Name = username;
will not set the name, unless you have setup the mock properly. Try this before assigning values to properties:
不会设置名称,除非您正确设置了模拟。在为属性赋值之前试试这个:
moqUser.SetupAllProperties();
This method will prepare all properties on the mock to be able to record the assigned value, and replay it later (i.e. to act as real property).
此方法将准备模拟上的所有属性,以便能够记录分配的值,并在稍后重播(即充当真实属性)。
You can also use SetupProperty()method to set up individual properties to be able to record the passed in value.
您还可以使用SetupProperty()方法来设置各个属性,以便能够记录传入的值。
Another approach is:
另一种方法是:
var mockUser = Mock.Of<User>( m =>
m.Name == "whatever" &&
m.Email == "[email protected]");
return mockUser;
回答by Sergey Berezovskiy
I think you are missing purpose of mocking. Mocks used to mock dependencies of class you are testing:
我认为你缺少嘲笑的目的。用于模拟您正在测试的类的依赖项的模拟:


System under test (SUT) should be tested in isolation (i.e. separate from other units). Otherwise errors in dependencies will cause your SUTs tests to fail. Also you should not write tests for mocks. That gives you nothing, because mocks are not production code. Mocks are not executed in your application.
被测系统 (SUT) 应单独测试(即与其他单元分开)。否则依赖项中的错误将导致您的 SUT 测试失败。此外,您不应该为模拟编写测试。那什么也没给你,因为模拟不是生产代码。模拟不在您的应用程序中执行。
So, you should mock CustomMembershipProvideronly if you are testing some unit, which depends on it (BTW it's better to create some abstraction like interface ICustomMembershipProviderto depend on).
因此,CustomMembershipProvider只有在测试某个依赖于它的单元时才应该模拟(顺便说一句,最好创建一些抽象,如ICustomMembershipProvider要依赖的接口)。
Or, if you are writing tests for CustomMembershipProviderclass, then it should not be mocked - only dependencies of this provider should be mocked.
或者,如果您正在为CustomMembershipProvider类编写测试,则不应模拟它 - 仅应模拟此提供程序的依赖项。

