我正在使用带有moq的NUnit框架进行测试。我已经遇到了这个类的私有方法被调用多少次的问题。要使用模拟对象,只需使用Times类型的参数调用Verify(),但我的方法是此类的一部分。我试图模拟当前的服务(SUT),但它可能不是最好的主意,它不能正常工作。
SUT:
public object Post(Operations.Campaign.Merge request)
{
List<CampaignIdWithNumberOfAds> campaignList = new List<CampaignIdWithNumberOfAds>();
for (int i = 0; i < request.CampaignIdsToMerge.Count; i++)
{
if (this.CampaignRepository.Exist(request.CampaignIdsToMerge[i]))
{
campaignList.Add(new CampaignIdWithNumberOfAds()
{
CampaignId = request.CampaignIdsToMerge[i],
NumberOfAdvertisement = this.CampaignRepository.GetNumberOfAdvertisementsInCampaign(request.CampaignIdsToMerge[i])
});
}
}
if (campaignList.Count > 1)
{
campaignList = campaignList.OrderByDescending(p => (p == null) ? -1 : p.NumberOfAdvertisement).ToList();
List<CampaignIdWithNumberOfAds> campaignsToMerge = campaignList.Skip(1).ToList();
CampaignIdWithNumberOfAds chosenCampaign = campaignList.FirstOrDefault<CampaignIdWithNumberOfAds>();
uint chosenCampaignId = chosenCampaign.CampaignId;
foreach (var campaignToMerge in campaignsToMerge)
{
this.MergeCampaigns(chosenCampaignId, campaignToMerge.CampaignId);
}
}
return true;
}
测试:
[Test]
public void MergeCampaignsPost_ValidMergeCampaignsRequest_ExecuteMergeCampaignsMethodAppropriateNumberOfTimes()
{
// Arrange
var mockCampaignService = new Mock<Toucan.Api.Services.CampaignService>();
var request = Mother.GetValidMergeCampaignsRequest_WithDifferentNumbersOfAdvertisement();
mockCampaignService.Setup(x => x.MergeCampaigns(It.IsAny<uint>(), It.IsAny<uint>()));
// Act
var response = this.Service.Post(request);
// Assert
mockCampaignService.Verify(x => x.MergeCampaigns(It.IsAny<uint>(), It.IsAny<uint>()), Times.Exactly(request.CampaignIdsToMerge.Count - 1));
}
答案 0 :(得分:1)
我担心我不会在这里给你一个解决方案,尽管我宁愿建议你一些指导。单元测试有许多不同的策略,不同的人会建议不同的解决方案。基本上在我看来,你可以改变你测试代码的方式(你可能会同意或不同意这些,但请考虑它们。)
听起来很简单,很难保持这种方法。私有方法是您解决问题的实现方式。开发人员为自己的代码编写单元测试的典型缺陷是,您知道代码如何工作并在单元测试中反映它。如果实施改变了,但公共方法仍将满足所请求的合同怎么办?你几乎不想用私人方法直接进行单元测试。这与以下内容有关......
这基本上意味着如果你不必要,不要检查某些事情的执行次数。我不确定你的MergeCampaigns
方法在做什么,但是如果检查操作的结果而不是执行它的次数会更好。
尝试使用尽可能简单且独立的测试来测试您可以想象的每个功能场景。不要过于深入地检查是否有人打电话。否则,您将在开始时获得100%的覆盖率,但每次更改服务中的内容时都会诅咒,因为这会使您的一半测试失败(假设该服务仍在执行其工作,但方式不同于设计在开头)。因此,您将花时间重写单元测试,这实际上在创建防弹解决方案方面没有任何好处。
很容易开始编写单元测试并保持覆盖绿色,如果你想编写良好的单元测试,它会变得非常棘手。有许多有价值的资源可以帮助解决这个问题。祝你好运!