FakeItEasy:模拟方法未返回预期结果
FakeItEasy: mocked method is not returning expected result
我在单元测试中使用 FakeItEasy 作为模拟框架。方法 fakeUserService.AddUser 被模拟为返回新的 MwbeUser 对象,方法 AddUser
中有一些非空值
A.CallTo(() => fakeUserService.AddUser(new MwbeUserRegistrationIn()
{
UserName = userName,
FirstName = firstName,
SecondName = secondName,
Password = passwd,
Email = email,
BirthDate = birthdate
})).Returns(new MwbeUser
{
UserName = userName,
Email = email,
FirstName = firstName,
SecondName = secondName,
BirthDate = birthdate
});
但它 returns 为空。为什么?
public void AddUserWithProperdata_UserIsAddedAndEmailIsGenerated()
{
// Arrange
String userName = "user";
String firstName = "Ala";
String secondName = "ADsadas";
String passwd = "passwd";
String email = "kot@wp.pl";
DateTime birthdate = DateTime.Today;
fakeUserService = A.Fake<IMwbeUserService>();
fakeAuthenticationService = A.Fake<IAuthenticationService>();
A.CallTo(() => fakeUserService
.AddUser(new MwbeUserRegistrationIn() { UserName = userName, FirstName = firstName, SecondName = secondName, Password = passwd, Email = email, BirthDate = birthdate }))
.Returns(new MwbeUser { UserName = userName, Email = email, FirstName = firstName, SecondName = secondName, BirthDate = birthdate });
MwbeUsersController controller = new MwbeUsersController(fakeUserService, fakeAuthenticationService);
MwbeUserRegistrationJson userjson = new MwbeUserRegistrationJson
{
username = userName,
passwd = passwd,
firstname = firstName,
secondname = secondName,
email = email,
birthdate = birthdate
};
// Act
IHttpActionResult untypedResult = controller.AddUser(userjson);
var test1 = untypedResult as OkResult;
var test2 = untypedResult as CreatedNegotiatedContentResult<MwbeUser>;
// Assert
Assert.IsNotNull(untypedResult);
}
public interface IMwbeUserService
{
MwbeUser AddUser(MwbeUserRegistrationIn regData);
...
}
更新 1:添加了控制器代码
[RoutePrefix("users")]
public class MwbeUsersController : ApiController
{
IMwbeUserService userSrv;
IAuthenticationService authService;
public MwbeUsersController(IMwbeUserService service, IAuthenticationService authSrv)
{
this.userSrv = service;
this.authService = authSrv;
}
...
[Route("register")]
[HttpPost]
public IHttpActionResult AddUser(MwbeUserRegistrationJson userdatadto)
{
// Validation
if (null == userdatadto)
{
return BadRequest("No user data");
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var registrationData = Conversion.ToUser(userdatadto);
if(registrationData.Code != MwbeResponseCodes.OK)
{
return BadRequest(registrationData.ErrorMessage);
}
// Registration
try
{
MwbeUser createdUser = userSrv.AddUser(registrationData.Data);
return Created<MwbeUser>("/users/" + createdUser.Id, createdUser);
}
catch (UserAlreadyExistsException)
{
return BadRequest("User with this username already exists");
}
catch (InvalidEmailAddress)
{
return BadRequest("Given e-mail address is invalid");
}
}
我对 FakeItEasy 没有什么经验,但我猜你的期望太严格了。
AddUser 的期望只有在使用被认为相等的对象调用时才会匹配(就像使用 object.Equals(object, object).
由于您的控制器传入了不同的 MwbeUserRegistrationIn 对象 (registrationData):
.AddUser(new MwbeUserRegistrationIn() {
UserName = userName,
FirstName = firstName,
SecondName = secondName,
Password = passwd,
Email = email,
BirthDate = birthdate }))
并且MwbeUserRegistrationIn大概不会覆盖object.Equals(object)
,这个期望不会被触发。您可以使用基于值的语义实现 MwbeUserRegistrationIn.Equals(object)
或通过称为 argument constraints.
的东西放宽您的期望
对于您的情况,您可以稍微重写一下期望值:
A.CallTo(() => fakeUserService.AddUser(A<MwbeUserRegistrationIn>.That.Matches(u =>
u.UserName == userName &&
u.FirstName == firstName &&
u.SecondName == secondName &&
u.Password == passwd &&
u.Email == email &&
u.BirthDate == birthdate)))
.Returns(new MwbeUser
{
UserName = userName,
Email = email,
FirstName = firstName,
SecondName = secondName,
BirthDate = birthdate
});
我在单元测试中使用 FakeItEasy 作为模拟框架。方法 fakeUserService.AddUser 被模拟为返回新的 MwbeUser 对象,方法 AddUser
中有一些非空值 A.CallTo(() => fakeUserService.AddUser(new MwbeUserRegistrationIn()
{
UserName = userName,
FirstName = firstName,
SecondName = secondName,
Password = passwd,
Email = email,
BirthDate = birthdate
})).Returns(new MwbeUser
{
UserName = userName,
Email = email,
FirstName = firstName,
SecondName = secondName,
BirthDate = birthdate
});
但它 returns 为空。为什么?
public void AddUserWithProperdata_UserIsAddedAndEmailIsGenerated()
{
// Arrange
String userName = "user";
String firstName = "Ala";
String secondName = "ADsadas";
String passwd = "passwd";
String email = "kot@wp.pl";
DateTime birthdate = DateTime.Today;
fakeUserService = A.Fake<IMwbeUserService>();
fakeAuthenticationService = A.Fake<IAuthenticationService>();
A.CallTo(() => fakeUserService
.AddUser(new MwbeUserRegistrationIn() { UserName = userName, FirstName = firstName, SecondName = secondName, Password = passwd, Email = email, BirthDate = birthdate }))
.Returns(new MwbeUser { UserName = userName, Email = email, FirstName = firstName, SecondName = secondName, BirthDate = birthdate });
MwbeUsersController controller = new MwbeUsersController(fakeUserService, fakeAuthenticationService);
MwbeUserRegistrationJson userjson = new MwbeUserRegistrationJson
{
username = userName,
passwd = passwd,
firstname = firstName,
secondname = secondName,
email = email,
birthdate = birthdate
};
// Act
IHttpActionResult untypedResult = controller.AddUser(userjson);
var test1 = untypedResult as OkResult;
var test2 = untypedResult as CreatedNegotiatedContentResult<MwbeUser>;
// Assert
Assert.IsNotNull(untypedResult);
}
public interface IMwbeUserService
{
MwbeUser AddUser(MwbeUserRegistrationIn regData);
...
}
更新 1:添加了控制器代码
[RoutePrefix("users")]
public class MwbeUsersController : ApiController
{
IMwbeUserService userSrv;
IAuthenticationService authService;
public MwbeUsersController(IMwbeUserService service, IAuthenticationService authSrv)
{
this.userSrv = service;
this.authService = authSrv;
}
...
[Route("register")]
[HttpPost]
public IHttpActionResult AddUser(MwbeUserRegistrationJson userdatadto)
{
// Validation
if (null == userdatadto)
{
return BadRequest("No user data");
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var registrationData = Conversion.ToUser(userdatadto);
if(registrationData.Code != MwbeResponseCodes.OK)
{
return BadRequest(registrationData.ErrorMessage);
}
// Registration
try
{
MwbeUser createdUser = userSrv.AddUser(registrationData.Data);
return Created<MwbeUser>("/users/" + createdUser.Id, createdUser);
}
catch (UserAlreadyExistsException)
{
return BadRequest("User with this username already exists");
}
catch (InvalidEmailAddress)
{
return BadRequest("Given e-mail address is invalid");
}
}
我对 FakeItEasy 没有什么经验,但我猜你的期望太严格了。
AddUser 的期望只有在使用被认为相等的对象调用时才会匹配(就像使用 object.Equals(object, object).
由于您的控制器传入了不同的 MwbeUserRegistrationIn 对象 (registrationData):
.AddUser(new MwbeUserRegistrationIn() {
UserName = userName,
FirstName = firstName,
SecondName = secondName,
Password = passwd,
Email = email,
BirthDate = birthdate }))
并且MwbeUserRegistrationIn大概不会覆盖object.Equals(object)
,这个期望不会被触发。您可以使用基于值的语义实现 MwbeUserRegistrationIn.Equals(object)
或通过称为 argument constraints.
对于您的情况,您可以稍微重写一下期望值:
A.CallTo(() => fakeUserService.AddUser(A<MwbeUserRegistrationIn>.That.Matches(u =>
u.UserName == userName &&
u.FirstName == firstName &&
u.SecondName == secondName &&
u.Password == passwd &&
u.Email == email &&
u.BirthDate == birthdate)))
.Returns(new MwbeUser
{
UserName = userName,
Email = email,
FirstName = firstName,
SecondName = secondName,
BirthDate = birthdate
});