我需要对以下原始方法进行起订量测试
public virtual User GetBOUser(string domainName, string userName, string password, Login model)
{
try
{
if (Sitecore.Security.Accounts.User.Exists(domainName + @"\" + userName))
{
User user = Sitecore.Security.Accounts.User.FromName(domainName + @"\" + userName, true);
return user;
}
}
catch (Exception ex)
{
Log.Error("GetBOUser Error - " + ex.ToString(), this);
}
return null;
}
我创建的示例单元测试方法如下
[TestMethod]
public void LoginApiTest()
{
User use = null;
var mockapi = new Mock<ApiController>();
mockapi.Setup(x => x.GetBOUser("", "", "", new Login())).Returns(use);
var dataObject = mockapi.Object;
Assert.AreEqual<User>(use, dataObject.GetBOUser("", "", "", new Login()));
}
这里我只能检查测试方法的返回类型中是否为 null,但是如何返回实际的
user
对象?
在回答您的问题之前,我需要指出您的示例测试实际上并没有测试任何东西。 您正在模拟被测试的系统,告诉它返回 null,然后断言它返回 null。 这不会执行您的生产代码。
您应该创建 ApiController 的一个普通实例。 然而,这凸显了另一个问题,即您的方法依赖于 Sitecore 的静态安全 API。 如果您希望您的代码可测试,您将需要为该 API 创建一个接口和包装类,并让您的控制器在其构造函数中接受接口的实例,以便您可以为您的测试提供一个模拟实例,但提供一个真实的实例正在生产中。
您的包装类应该只调用静态 API 并且不应该包含任何逻辑。 这样你就不需要真正测试它了。 当您设置界面的模拟实例时,您可以创建一个模拟 IPrincipal 并将其传递给 User.FromPrincipal 以防止它实际尝试在数据库中查找用户。 如果您将接口命名为 IUserService,您的测试最终将看起来像这样:
[TestMethod]
public void GetBOUser_WithExistingUser_ReturnsUser()
{
// Arrange
var name = "Joe";
var domain = "extranet";
var fullName = domain + @"\" + name;
var principal = new Mock<IPrincipal>();
principal.Setup(p => p.Identity.Name).Returns(fullName);
var joeUser = User.FromPrincipal(principal.Object);
var userService = new Mock<IUserService>();
userService.Setup(u => u.Exists(fullName)).Returns(true);
userService.Setup(u => u.FromName(fullName)).Returns(joeUser.Object);
var controller = new ApiController(userService.Object);
// Act
var result = controller.GetBOUser("extranet", "Joe", "password", new Login());
// Assert
Assert.AreEqual(fullName, result.Name);
}
另一件事...您的 GetBOUser 方法接受密码,但在返回用户之前不会验证它。 这对 API 的消费者来说是非常误导的。 如果您接受密码,则应在返回请求的用户对象之前确保密码正确。