簡體   English   中英

如何在 C# 的 CQRS 模式中對命令處理程序進行單元測試

[英]How to unit test Command Handler in CQRS pattern in C#

我正在 C# 中學習和練習 CQRS 和單元測試。 我需要知道如何在 CQRS 中對命令處理程序進行單元測試。

這是我的CreateAuthorCommand

public sealed class CreateAuthorCommand : ICommand<Author>
{
    public CreateAuthorCommand(string firstName, string lastName, DateTimeOffset dateOfBirth, string mainCategory, IEnumerable<CreateBookDto> books)
    {
        FirstName = firstName;
        LastName = lastName;
        DateOfBirth = dateOfBirth;
        MainCategory = mainCategory;
        Books = books;
    }

    public string FirstName { get; }
    public string LastName { get; }
    public DateTimeOffset DateOfBirth { get; private set; }
    public string MainCategory { get; }
    public IEnumerable<CreateBookDto> Books { get; }

    [AuditLog]
    [DatabaseRetry]
    internal sealed class AddCommandHandler : ICommandHandler<CreateAuthorCommand, Author>
    {
        private readonly IUnitOfWork _unitOfWork;

        public AddCommandHandler(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
        }

        public async Task<Result<Author>> Handle(CreateAuthorCommand command)
        {
            var nameResult = Name.Create(command.FirstName, command.LastName);
            var birthDateResult = BirthDate.Create(command.DateOfBirth);
            var mainCategoryResult = Entities.Authors.MainCategory.Create(command.MainCategory);

            var authorResult = Result.Combine(nameResult, birthDateResult, mainCategoryResult)
                                .Map(() => new Author(nameResult.Value, birthDateResult.Value, null, mainCategoryResult.Value));
                
            if (authorResult.IsFailure)
                return Result.Failure<Author>(authorResult.Error);

            await _unitOfWork.AuthorRepository.AddAsync(authorResult.Value);

            await _unitOfWork.SaveChangesAsync();

            return Result.Success(authorResult.Value);
        }
    }
}

這是我的單元測試:

public class CreateAuthorCommandTests
{
    [Fact]
    public void Create_Author_Should_Call_Add_Method_Once() 
    {
        var fixture = new Fixture();
        var command = fixture.Create<CreateAuthorCommand>();
        var mockUnitOfWork = new Mock<IUnitOfWork>();
        var mockHandler = new Mock<ICommandHandler<CreateAuthorCommand, Author>>();

        var result = mockHandler.Object.Handle(command);

        mockUnitOfWork.Verify(x => x.AuthorRepository.AddAsync(It.IsAny<Author>()), Times.Once);
    }
}

當我調試上述測試時,

  1. 我無法進入處理程序方法!
  2. 如何將mockUnitOfWork作為構造函數參數傳遞給AddCommandHandler

如果我可以通過mockUnitOfWork ,我可以在我的AuthorRepository中驗證AddAsync調用。 請協助我做錯了什么。

您正在測試處理程序,所以不是這個

var result = mockHandler.Object.Handle(command);

...創建一個實際的 AddCommandHandler 實例並注入它所需的依賴項,即

var mockUnitOfWork = new Mock<IUnitOfWork>();
var handler = new AddCommandHandler(mockUnitOfWork.Object);

當您調用Handle時,您現在將進入您的實現。

如果您想保留 Internal 訪問修飾符,您可以使用 InternalsVisibleTo 屬性來授予對您的測試項目的訪問權限,例如在定義處理程序的項目中執行此操作,

[assembly: InternalsVisibleTo(“UnitTests”)]

https://anthonygiretti.com/2018/06/27/how-to-unit-test-internal-classes-in-net-core-applications/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM