如何使用在方法中具有依赖性的最小起订量对 class 进行单元测试?
How to unit test a class using moq that has dependencies within a method?
我想对验证用户身份的 class AuthClient
(使用 Moq
)进行单元测试。
问题是我的 AuthenticationService
依赖项没有注入 class。我对如何在不注入依赖项的情况下测试流程感到有点困惑。
[TestClass]
public class AuthClient
{
string Dictionary<string, IList<UserPermissions> _userPermissions;
User Login(string username, string password)
{
IAuthenticationService authenticationService = new AuthenticationService();
User user = authService.Login(username, password);
IAuthorizationService authorizationService = new AuthorizationService();
var permissions = authorizationService.GetPermissions(user);
_userPermissions.Add(user.Username, permissions);
return user;
}
}
我当前的单元测试代码如下所示:
public class UnitTestClass
{
public string UserName {get;set;}
public string Password {get;set;}
[TestInitialize]
public void Setup()
{
UserName = "test";
Password = "test123";
}
[TestMethod]
public void When_ValidUserCredentials_Expect_UserIsNotNull()
{
var mockAuthenticationService = new Mock<IAuthenticateService>();
mockAuthenticationService.Setup(m => m.Login(ValidUserName, ValidPassword)).Returns(ValidUserDto);
var mockAuthorizationService = new Mock<IAuthorizeService>();
mockAuthorizationService.Setup(m => m.GetAllPermissions(ValidUserId)).Returns(ValidPermissionList);
var authClient = new Mock<AuthClient>();
// I want to use mock dependencies here to test flow against mock data
User user = authClient.Login(UserName, Password);
Assert.IsNotNull(user);
}
}
有什么地方出了问题吗?
Moq 允许您测试 class 依赖于其他 classes/object 的元素(以及许多其他东西)。
注意:Moq 不是 IOC 容器。
在您的 AuthClient class 中,您不允许为其提供任何依赖项,而是实例化其自身,例如
IAuthenticationService authenticationService = new AuthenticationService();
相反,您需要在 AuthClient class 上定义一个构造函数,它接受两个对象(它应该依赖于它们),还有其他方法可以 "inject" 依赖关系,但现在我们将使用构造函数注入 (good example)
例如
public class AuthClient
{
string Dictionary<string, IList<UserPermissions> _userPermissions;
private IAuthenticationService _authenticationService;
private IAuthorizationService _authorizationService;
public AuthClient(IAuthenticationService authenticationService, IAuthorizationService authorizationService)
{
_authenticationService = authenticationService;
_authorizationService = authorizationService;
}
User Login(string username, string password)
{
User user = _authenticationService.Login(username, password);
var permissions = _authorizationService.GetPermissions(user);
_userPermissions.Add(user.Username, permissions);
return user;
}
}
现在,每次您想使用这个 class 时,您都必须告诉它应该使用哪个授权服务和身份验证服务。您已经将 AuthClient 与特定实现分离 - 现在它非常可测试和可重用(如果您想创建一个新的 AuthenticationService 来做一些与旧的完全不同的事情,您只需要编写一个 class实施 IAuthenticationService!)
您现在必须在每次要使用它时包含 AuthClient 的依赖项(将其提供给它的构造函数)。
你应该阅读更多关于依赖注入和 IOC(控制反转)的内容(这是一个非常大的话题,有很多不同的方法来做同样的事情),google 是你的朋友。
测试 class 现在应该如下所示:
public class UnitTestClass
{
public string UserName {get;set;}
public string Password {get;set;}
[TestInitialize]
public void Setup()
{
UserName = "test";
Password = "test123";
}
[TestMethod]
public void When_ValidUserCredentials_Expect_UserIsNotNull()
{
var mockAuthenticationService = new Mock<IAuthenticateService>();
mockAuthenticationService.Setup(m => m.Login(ValidUserName, ValidPassword)).Returns(ValidUserDto);
var mockAuthorizationService = new Mock<IAuthorizeService>();
mockAuthorizationService.Setup(m => m.GetAllPermissions(ValidUserId)).Returns(ValidPermissionList);
// Here we are "injecting" the dependencies into the AuthClient
var authClient = new AuthClient(mockAuthenticationService.Object, mockAuthorizationService.Object);
// This service call will now use the supplied (mocked) services above
User user = authClient.Login(UserName, Password);
Assert.IsNotNull(user);
}
}
我想对验证用户身份的 class AuthClient
(使用 Moq
)进行单元测试。
问题是我的 AuthenticationService
依赖项没有注入 class。我对如何在不注入依赖项的情况下测试流程感到有点困惑。
[TestClass]
public class AuthClient
{
string Dictionary<string, IList<UserPermissions> _userPermissions;
User Login(string username, string password)
{
IAuthenticationService authenticationService = new AuthenticationService();
User user = authService.Login(username, password);
IAuthorizationService authorizationService = new AuthorizationService();
var permissions = authorizationService.GetPermissions(user);
_userPermissions.Add(user.Username, permissions);
return user;
}
}
我当前的单元测试代码如下所示:
public class UnitTestClass
{
public string UserName {get;set;}
public string Password {get;set;}
[TestInitialize]
public void Setup()
{
UserName = "test";
Password = "test123";
}
[TestMethod]
public void When_ValidUserCredentials_Expect_UserIsNotNull()
{
var mockAuthenticationService = new Mock<IAuthenticateService>();
mockAuthenticationService.Setup(m => m.Login(ValidUserName, ValidPassword)).Returns(ValidUserDto);
var mockAuthorizationService = new Mock<IAuthorizeService>();
mockAuthorizationService.Setup(m => m.GetAllPermissions(ValidUserId)).Returns(ValidPermissionList);
var authClient = new Mock<AuthClient>();
// I want to use mock dependencies here to test flow against mock data
User user = authClient.Login(UserName, Password);
Assert.IsNotNull(user);
}
}
有什么地方出了问题吗?
Moq 允许您测试 class 依赖于其他 classes/object 的元素(以及许多其他东西)。 注意:Moq 不是 IOC 容器。
在您的 AuthClient class 中,您不允许为其提供任何依赖项,而是实例化其自身,例如
IAuthenticationService authenticationService = new AuthenticationService();
相反,您需要在 AuthClient class 上定义一个构造函数,它接受两个对象(它应该依赖于它们),还有其他方法可以 "inject" 依赖关系,但现在我们将使用构造函数注入 (good example)
例如
public class AuthClient
{
string Dictionary<string, IList<UserPermissions> _userPermissions;
private IAuthenticationService _authenticationService;
private IAuthorizationService _authorizationService;
public AuthClient(IAuthenticationService authenticationService, IAuthorizationService authorizationService)
{
_authenticationService = authenticationService;
_authorizationService = authorizationService;
}
User Login(string username, string password)
{
User user = _authenticationService.Login(username, password);
var permissions = _authorizationService.GetPermissions(user);
_userPermissions.Add(user.Username, permissions);
return user;
}
}
现在,每次您想使用这个 class 时,您都必须告诉它应该使用哪个授权服务和身份验证服务。您已经将 AuthClient 与特定实现分离 - 现在它非常可测试和可重用(如果您想创建一个新的 AuthenticationService 来做一些与旧的完全不同的事情,您只需要编写一个 class实施 IAuthenticationService!)
您现在必须在每次要使用它时包含 AuthClient 的依赖项(将其提供给它的构造函数)。 你应该阅读更多关于依赖注入和 IOC(控制反转)的内容(这是一个非常大的话题,有很多不同的方法来做同样的事情),google 是你的朋友。
测试 class 现在应该如下所示:
public class UnitTestClass
{
public string UserName {get;set;}
public string Password {get;set;}
[TestInitialize]
public void Setup()
{
UserName = "test";
Password = "test123";
}
[TestMethod]
public void When_ValidUserCredentials_Expect_UserIsNotNull()
{
var mockAuthenticationService = new Mock<IAuthenticateService>();
mockAuthenticationService.Setup(m => m.Login(ValidUserName, ValidPassword)).Returns(ValidUserDto);
var mockAuthorizationService = new Mock<IAuthorizeService>();
mockAuthorizationService.Setup(m => m.GetAllPermissions(ValidUserId)).Returns(ValidPermissionList);
// Here we are "injecting" the dependencies into the AuthClient
var authClient = new AuthClient(mockAuthenticationService.Object, mockAuthorizationService.Object);
// This service call will now use the supplied (mocked) services above
User user = authClient.Login(UserName, Password);
Assert.IsNotNull(user);
}
}