我正在使用干净的架构,并为我的应用程序层创建测试。我的问题是测试用例失败,因为_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
。但又失败了。
1条答案
按热度按时间fykwrbwg1#
我打赌
ToDomainModel
只是创建了一个新的类示例,它没有覆盖Equals
(所以Moq
无法匹配参数,并返回Guid
的默认值)。使用一些匹配逻辑将Setup
调用中的_successMovie.ToMovieDomainModel()
更改为It.IsAny<Movie>
或It.Is
:字符串
在这种情况下,有时切换到严格模式(当尝试调用非设置成员时抛出)可能很有用:
让mock表现得像一个“真正的Mock”,为没有相应期望的任何东西引发异常:在Moq俚语中是“严格”的嘲弄;默认行为是“松散”模拟,它从不抛出和返回默认值或空数组、可枚举对象等。如果没有为成员设置期望
型
另请阅读:
Moq快速入门:匹配参数