单元测试使用存储库模式编写的代码

时间:2019-11-13 13:18:58

标签: c# repository-pattern

我已使用存储库模式实现了我的业务逻辑。我的控制器中基本上有批准方法。我正在调用服务方法ApproveUserChangeRequest 依次调用UnitofWork类中的GetUserChangeRequest和ApproveUserChangeRequest。我想知道这是标准的还是更好的方法 请牢记测试服务方法

UserConroller

[HttpPost]
[AllowAnonymous]
[Route("approve-change-request")]
public IActionResult ApproveUserChangeRequest([FromBody] ApproveUserChangeRequests approveUserChangeRequests)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(new ResponseModel()
        {
            ResponseMessages = new Dictionary<string, string[]>
            {
                { "Errors", ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage).ToArray() }
            }
        });
    }    

    var result  = _userService.ApproveUserChangeRequest(approveUserChangeRequests);
    var message = string.Empty;
    if (result.Succeeded)
    {
        return Ok(new ResponseModel()
        {
            ResponseMessages = new Dictionary<string, string[]>
            {
               { "Info", new string[] { $"True" } }
            }
        });
    }
    message = string.Join(";", result.Errors.Select(x => $"Code: {x.Code}. Description: {x.Description}"));
    _logger.Error(new IdentityException($"Error approving user change requests. Message: {message}"));
    return BadRequest();

}

UserService类

public  IdentityResult ApproveUserChangeRequest(ApproveUserChangeRequests approveUserChangeRequests)
{
    var userChangeRequest = _userUow.GetUserChangeRequest(approveUserChangeRequests.UserChangeRequestID);

    IdentityResult result =  _userUow.ApproveUserChangeRequest(userChangeRequest, approveUserChangeRequests.ApprovedByAuthUserId, approveUserChangeRequests.AuthApplicationName);
    return result;
}    

UnitofWork类(uow)

public UserChangeRequest GetUserChangeRequest(int userChangeRequestId)
{
    return UserChangeRequestRepository.GetQueryable(x =>
        x.Id == userChangeRequestId)
        .FirstOrDefault();
}


public IdentityResult ApproveUserChangeRequest(UserChangeRequest userChangeRequest, int approvedByAuthUserId, string authApplicationName)
{
    var idResult = IdentityResult.Success;

    // Check if UserChangeRequest is still Pending
    bool isUserChangeRequestPending = UserChangeRequestRepository.GetQueryable(x => x.Id == userChangeRequest.Id && x.ChangeStatus == "Pending").Any();

    if (isUserChangeRequestPending && approvedByAuthUserId > 0)
    {
        // Inserting record in the UserChangeRequestApproval table
        InsertUserChangeRequestApproval(userChangeRequest);
        SaveContext();

        //Updating the user details in IdentityDB, ClientCompanyContact and AuthUser tables 
        UpdateUserDetails(userChangeRequest, authApplicationName);
    }
    else
    {
        idResult = IdentityResult.Failed(new IdentityError { Description = "No userchange request to approve" });
    }
    return idResult;
}

1 个答案:

答案 0 :(得分:0)

仅隔离测试应用程序的每个部分很重要。在测试public IActionResult ApproveUserChangeRequest时,我们只想确保它正确地完成了自己的工作。它调用的所有内容均应进行模拟,并分别进行测试。

为此,您将需要为存储库和UnitOfWork类创建接口。这样可以模拟他们并模拟他们的行为。

您还应该允许使用依赖注入将这些类注入到消费类中,例如:

private readonly IUserService _userService;

public MyController(IUserService userService)
{
    _userService = userService;
}

public IActionResult ApproveUserChangeRequest([FromBody] ApproveUserChangeRequests approveUserChangeRequests)
{
    // ... snip
    // this now uses the instance that was provided by dependency injection
    var result = _userService.ApproveUserChangeRequest(approveUserChangeRequests);
}

然后,您可以在模拟用户服务行为的同时测试您的类/方法。以下示例使用Moq,但您可以使用其他模拟框架。

public void ApproveUserChangeRequest_PassesApproveChangeRequestsModelToService()
{
    // mock the user service
    var userService = new Mock<IUserService>();
    // provide the controller with the user service
    var controller = new MyController(userService);
    // create the model for the request
    var model = new ApproveUserChangeRequests();
    // test the method
    controller.ApproveUserChangeRequest(model);

    // make sure that userService.ApproveUserChangeRequest was called with the correct arguments
    userService.Verify(u => u.ApproveUserChangeRequest(model));
}

在Controller的单元测试中,您仅需要检查ApproveUserChangeRequest是否正确执行了它的工作。那是

  • 验证模型
  • 如果模型无效,则会引发错误
  • 调用用户服务(如果有效)
  • 成功发送正确的响应
  • 正确登录到记录器
  • 在适当的情况下回应错误的请求

这些都应在单独的单元测试中进行检查。

然后,您还应该为UserService和UnitOfWork类编写测试。只为那些类负责的事情编写测试。如果您发现类负责太多事情,请重构您的类,直到它遵循单一责任原则,这将极大地帮助您测试代码。