【问题标题】:Unit testing the code that is written using repository pattern对使用存储库模式编写的代码进行单元测试
【发布时间】:2019-11-13 21:41:47
【问题描述】:

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

用户控制器

[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();

}

用户服务类

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;
}

【问题讨论】:

标签: c# repository-pattern


【解决方案1】:

仅单独测试应用程序的每个部分非常重要。当我们测试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));
}

在控制器的单元测试中,您只需要检查 ApproveUserChangeRequest 是否正确地完成了它的工作。那就是

  • 验证您的模型
  • 如果模型无效则引发错误
  • 如果有效则调用用户服务
  • 如果成功则向您发送正确的响应
  • 正确记录到您的记录器
  • 适当时响应错误请求

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-14
    • 2020-10-17
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-26
    相关资源
    最近更新 更多