asp.net 返回带有.Moq的Guid的模拟方法

qni6mghb  于 2023-08-08  发布在  .NET
关注(0)|答案(1)|浏览(128)

我正在使用干净的架构,并为我的应用程序层创建测试。我的问题是测试用例失败,因为_movieRepository.CreateAsync()返回了一个空的Guid,它是“0000000 - 0000 - 0000-0000- 00000000000”,而不是用“CF 0A 8 C1 C-F2 D 0 - 41 A1-A12 C-53 D9 BE 513 A1 C”填充
这是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;
        }


希望有人能发现这个错误并帮助我。
祝你今天愉快
我尝试了.Returns(Task.FromResult(sampleGuid));而不是.ReturnsAsync()方法,但没有解决这个问题。我还尝试为两个模拟生成唯一的随机Guid.NewGuid(),而不是变量sampleGuid。但又失败了。

fykwrbwg

fykwrbwg1#

我打赌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);

字符串
在这种情况下,有时切换到严格模式(当尝试调用非设置成员时抛出)可能很有用:
让mock表现得像一个“真正的Mock”,为没有相应期望的任何东西引发异常:在Moq俚语中是“严格”的嘲弄;默认行为是“松散”模拟,它从不抛出和返回默认值或空数组、可枚举对象等。如果没有为成员设置期望

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


另请阅读:
Moq快速入门:匹配参数

相关问题