如何使用 Moq 在 .NET 6 的以下代码中模拟方法?
How to mock methods in the below code in the .NET 6 using Moq?
下面是需要测试的InvokeAsync方法。
public async Task<bool> InvokeAsync(Batch batch)
{
var refundRequests = await this.RefundRepository.GetsAsync(batch.RefundRequests.Select(x => x.Id));
refundRequests.RemoveAll(x => x.Status != RefundRequestStatus.Approved);
var distributions = await DistributionRepository.GetsAsync(refundRequests.Select(x => x.Distribution.Id));
var bundles = await this.BundleRepository.GetsAsync(distributions.Select(x => x.BundleId));
foreach (var getRefundRequest in refundRequests)
{
var distribution = distributions.FirstOrDefault(x => x.Id == getRefundRequest.Distribution.Id);
if (distribution?.BundleId != null)
{
var bundle = bundles.First(x => x.Id == distribution?.BundleId);
Bundle result = await Reverse.InvokeAsync(getRefundRequest, distribution, bundle); //MOCK
}
getRefundRequest.Status = RefundRequestStatus.Closed;
getRefundRequest.LastUpdatedBy = "Test User";
bool isUpdated = await UpdateRefund.InvokeAsync(getRefundRequest); //MOCK
}
batch.Status = BatchStatus.Posted;
batch.LastUpdatedBy = "Test User";
var isSuccess = await UpdateBatch.InvokeAsync(batch); //MOCK
return isSuccess;
}
单元测试方法
[Fact]
public async Task Post_Batch()
{
foreach (var refundBatch in Factory.Batch.CreateRefundBatchesData())
{
var refundRequests = await this.RefundRequestRepository.GetsAsync(batch.RefundRequests.Select(x => x.Id));
var distributions = await this.DistributionRepository.GetsAsync(refundRequests.Select(x => x.Distribution.Id));
var bundles = await this.BundleRepository.GetsAsync(distributions.Select(x => x.BundleId));
for (int i = 0; i < refundRequests.Count; i++)
{
var refundRequest = refundRequests[i];
var bundle = bundles[i];
var distribution = distributions[i];
MockSetupReverse(refundRequest, distribution, bundle);
MockSetupUpdateRefund(refundRequest);
}
MockSetupUpdateBatch(batch);
//Act
var postRefund = await UseCase.InvokeAsync(batch);
//Assert
postRefund.ShouldNotBeNull();
postRefund.IsPosted.ShouldBeTrue();
}
}
MockSetup 方法
private void MockSetupReverse(RefundRequest refundRequest, Distribution distribution, Bundle bundle)
{
this.MockReverse
.Setup(x => x.InvokeAsync(refundRequest, distribution, bundle))
.Returns(async () =>
{
bundle.Status = BundleStatus.Closed;
return await Task.Run(() => bundle);
});
}
private void MockSetupUpdateRefund(RefundRequest refundRequest)
{
this.MockUpdateRefund
.Setup(x => x.InvokeAsync(refundRequest))
.Returns(async () =>
{
refundRequest.Status = RefundRequestStatus.Closed;
refundRequest.LastUpdatedBy = Factory.RefundRequest.TestUserName;
return await Task.Run(() => true);
});
}
private void MockSetupUpdateBatch(Batch batch)
{
this.MockUpdateBatch
.Setup(x => x.InvokeAsync(batch))
.Returns(async () =>
{
refundBatch.Status = BatchStatus.Posted;
refundBatch.LastUpdatedBy = Factory.RefundRequest.TestUserName;
return await Task.Run(() => true);
});
}
UpdateBatch 的模拟是 working 和 returns true when该方法被调用。但是,当相应的方法是调用。有什么想法吗?
如果需要更多信息来支持该问题,请告诉我。
当您 Setup
使用特定参数模拟时,Returns
仅在使用此特定参数时适用。
UpdateBatch
起作用的原因是因为您在模拟和被测 class 中使用了对相同 Batch
的相同引用:
MockSetupUpdateBatch(batch);
//Act
var postRefund = await UseCase.InvokeAsync(batch); // <---- Same "batch"
当您的测试代码调用 RefundRequestRepository.GetsAsync
时,您可能会得到与被测试的 class 调用 GetsAsync
时不同的结果,因此设置与被测试的 [=] 的调用无关=27=] 并且可能 returns 默认布尔值 (false
).
有关如何正确模拟的更多信息,请参阅 this GitHub page
下面是需要测试的InvokeAsync方法。
public async Task<bool> InvokeAsync(Batch batch)
{
var refundRequests = await this.RefundRepository.GetsAsync(batch.RefundRequests.Select(x => x.Id));
refundRequests.RemoveAll(x => x.Status != RefundRequestStatus.Approved);
var distributions = await DistributionRepository.GetsAsync(refundRequests.Select(x => x.Distribution.Id));
var bundles = await this.BundleRepository.GetsAsync(distributions.Select(x => x.BundleId));
foreach (var getRefundRequest in refundRequests)
{
var distribution = distributions.FirstOrDefault(x => x.Id == getRefundRequest.Distribution.Id);
if (distribution?.BundleId != null)
{
var bundle = bundles.First(x => x.Id == distribution?.BundleId);
Bundle result = await Reverse.InvokeAsync(getRefundRequest, distribution, bundle); //MOCK
}
getRefundRequest.Status = RefundRequestStatus.Closed;
getRefundRequest.LastUpdatedBy = "Test User";
bool isUpdated = await UpdateRefund.InvokeAsync(getRefundRequest); //MOCK
}
batch.Status = BatchStatus.Posted;
batch.LastUpdatedBy = "Test User";
var isSuccess = await UpdateBatch.InvokeAsync(batch); //MOCK
return isSuccess;
}
单元测试方法
[Fact]
public async Task Post_Batch()
{
foreach (var refundBatch in Factory.Batch.CreateRefundBatchesData())
{
var refundRequests = await this.RefundRequestRepository.GetsAsync(batch.RefundRequests.Select(x => x.Id));
var distributions = await this.DistributionRepository.GetsAsync(refundRequests.Select(x => x.Distribution.Id));
var bundles = await this.BundleRepository.GetsAsync(distributions.Select(x => x.BundleId));
for (int i = 0; i < refundRequests.Count; i++)
{
var refundRequest = refundRequests[i];
var bundle = bundles[i];
var distribution = distributions[i];
MockSetupReverse(refundRequest, distribution, bundle);
MockSetupUpdateRefund(refundRequest);
}
MockSetupUpdateBatch(batch);
//Act
var postRefund = await UseCase.InvokeAsync(batch);
//Assert
postRefund.ShouldNotBeNull();
postRefund.IsPosted.ShouldBeTrue();
}
}
MockSetup 方法
private void MockSetupReverse(RefundRequest refundRequest, Distribution distribution, Bundle bundle)
{
this.MockReverse
.Setup(x => x.InvokeAsync(refundRequest, distribution, bundle))
.Returns(async () =>
{
bundle.Status = BundleStatus.Closed;
return await Task.Run(() => bundle);
});
}
private void MockSetupUpdateRefund(RefundRequest refundRequest)
{
this.MockUpdateRefund
.Setup(x => x.InvokeAsync(refundRequest))
.Returns(async () =>
{
refundRequest.Status = RefundRequestStatus.Closed;
refundRequest.LastUpdatedBy = Factory.RefundRequest.TestUserName;
return await Task.Run(() => true);
});
}
private void MockSetupUpdateBatch(Batch batch)
{
this.MockUpdateBatch
.Setup(x => x.InvokeAsync(batch))
.Returns(async () =>
{
refundBatch.Status = BatchStatus.Posted;
refundBatch.LastUpdatedBy = Factory.RefundRequest.TestUserName;
return await Task.Run(() => true);
});
}
UpdateBatch 的模拟是 working 和 returns true when该方法被调用。但是,当相应的方法是调用。有什么想法吗?
如果需要更多信息来支持该问题,请告诉我。
当您 Setup
使用特定参数模拟时,Returns
仅在使用此特定参数时适用。
UpdateBatch
起作用的原因是因为您在模拟和被测 class 中使用了对相同 Batch
的相同引用:
MockSetupUpdateBatch(batch);
//Act
var postRefund = await UseCase.InvokeAsync(batch); // <---- Same "batch"
当您的测试代码调用 RefundRequestRepository.GetsAsync
时,您可能会得到与被测试的 class 调用 GetsAsync
时不同的结果,因此设置与被测试的 [=] 的调用无关=27=] 并且可能 returns 默认布尔值 (false
).
有关如何正确模拟的更多信息,请参阅 this GitHub page