我正在使用干净的架构,并为我的应用层创建测试.我的问题是,测试用例失败是因为返回了一个空的Guid,即"00000000-0000-0000-0000-000000000000",而不是用"CF0A8C1C-F2D0-41A1-A12C-53D9BE513A1C"填充

这是Fixture类:

public class MovieFixture
    {
        private readonly Mock<IMovieRepository> _movieRepository = new Mock<IMovieRepository>();
        private ServiceCollection ServiceCollection { get; } = new ServiceCollection();

        public CreateMovieCommandHandler CreateMovieCommandHandler
        {
            get
            {
                ServiceProvider serviceProvider = ServiceCollection.BuildServiceProvider();
                CreateMovieCommandHandler service = serviceProvider.GetRequiredService<CreateMovieCommandHandler>();
                return service;
            }
        }

        public MovieFixture()
        {
            var sampleGuid = new Guid("{CF0A8C1C-F2D0-41A1-A12C-53D9BE513A1C}");
            #region Movie command handler mocks

            // Create movie.
            _movieRepository
                .Setup(x => x.CreateAsync(_successMovie.ToMovieDomainModel()))
                .ReturnsAsync(sampleGuid);

            _movieRepository
                .Setup(x => x.CreateAsync(_failedMovie))
                .ReturnsAsync(Guid.Empty);

            #endregion

            #region Add transient services
            AddServices();
            #endregion
        }

        private void AddServices()
        {
            // Add repository mock
            _ = ServiceCollection.AddTransient(_ => _movieRepository.Object);

            // Add handlers
            _ = ServiceCollection.AddTransient<CreateMovieCommandHandler>();

            // Add validator
            _ = ServiceCollection.AddTransient<MovieValidator<CreateMovieCommand>>();
        }

        private CreateMovieCommand _successMovie = new CreateMovieCommand
        {
            Name = "success",
            Description = "test",
            IsActive = true,
            IsExpired = false,
            Image = "some-image.png",
            StartDate = DateTime.Now
        };

        private Movie _failedMovie = new Movie
        {
            Name = "failed",
            Description = "test",
            IsActive = true,
            IsExpired = false,
            Image = "some-image.png",
            StartDate = DateTime.Now
        };

这就是失败的实际测试用例

[Fact]
        public async Task Handle_WhenRepositoryReturnsSuccess_ShouldReturnUnitValue()
        {
            // Arrange
            Exception? exception = default;
            var handler = _movieFixture.CreateMovieCommandHandler;
            Unit result = default;

            // Act
            try
            {
                result = await handler.Handle(_successMovie, CancellationToken.None);
            }
            catch (Exception ex)
            {
                exception = ex;
            }

            //Assert
            exception.Should().BeNull();
            result.Should().Be(Unit.Value);
        }

这里也是命令处理程序.

public async Task<Unit> Handle(CreateMovieCommand request, CancellationToken cancellationToken)
        {
            var validationResult = await _validator.ValidateAsync(request).ConfigureAwait(false);

            if (validationResult.IsValid is false)
                throw new ValidationException(validationResult.Errors.FirstOrDefault()?.ToString());

            var result = await _movieRepository.CreateAsync(request.ToMovieDomainModel()).ConfigureAwait(false);

            if (result == Guid.Empty)
                throw new MovieCannotBeAddedException(ErrorMessages.MovieCannotBeAdded);

            return Unit.Value;
        }

希望有人能认出这个错误并帮助我.

祝你有愉快的一天.

我try 了.Returns(Task.FromResult(sampleGuid));种方法而不是.ReturnsAsync()种方法,但没有解决这个问题.我还try 为两个模拟生成唯一的随机Guid.NewGuid(),而不是变量sampleGuid.但又失败了.

推荐答案

我打赌ToDomainModel只是创建了一个没有覆盖Equals的类的新实例(因此Moq无法匹配参数并返回Guid的缺省值).使用一些匹配的逻辑将Setup调用中的_successMovie.ToMovieDomainModel()更改为It.IsAny<Movie>It.Is:

_movieRepository
    .Setup(x => x.CreateAsync(It.Is<Movie>(movie => movie.Name == _successMovie.Name)))
    .ReturnsAsync(sampleGuid);

在这种情况下,有时切换到严格模式很有用(在try 调用NOT SETUP成员时抛出):

使Mock的行为类似于"True Mock",为任何没有相应期望的事物抛出异常:在Moq俚语中是"严格的"Mock;默认行为是"松散的"Mock,如果没有为成员设置期望,它永远不会抛出和返回缺省值或空数组、可枚举等

private readonly Mock<IMovieRepository> _movieRepository = 
    new Mock<IMovieRepository>(MockBehavior.Strict);

另请阅读:

Moq Quickstart: Matching Arguments

Csharp相关问答推荐

Blazor:计算值或保留为默认值

需要深入了解NpgSQL DateTimeOffset处理

为什么EF Core 6会针对null验证Count(*)?

ASP.NET MVC中创建视图的过滤器

使用C#中的SDK在Microsoft Graph API上使用SubscribedSkus的问题

Take()方法如何与IAsyncEnumerable一起使用

使用两个不同的枚举作为Switch语句中的CASE生成唯一值

从.Net 6 DLL注册和检索COM对象(Typelib导出:类型库未注册.(异常来自HRESULT:0x80131165))

当我没有此令牌时,为什么语法报告EOF错误?

JsonSchema.Net删除假阳性判断结果

Blazor Fluent UI DialogService,<;FluentDialogProvider/>;错误

在C#中,当输入一个方法/局部函数时,我的IEnumerator被重置/重新创建.为什么?

C# Winforms:从对象树到TreeView的递归转换重复条目

RCL在毛伊岛应用程序和Blazor服务器应用程序.Net 8.0中使用页面

使用Blazor WebAssembly提高初始页面加载时间的性能

如何正确地在VB中初始化类?

为什么我的属性即使没有显式地设置任何[必需]属性,也会显示验证?

在C#中通过Matheval使用自定义公式

C#;AvaloniaUI;MVVM;当另一个窗口上的按钮被单击时,如何更新视图图像源?

读取测试项目中的应用程序设置