C#具有Moq的单元测试在单独运行和作为集合的一部分运行时表现不同

C#具有Moq的单元测试在单独运行和作为集合的一部分运行时表现不同,c#,unit-testing,moq,C#,Unit Testing,Moq,我有一个单元测试,它验证(使用Moq)一个特定函数被调用了多少次。应该叫两次 在VisualStudio中右键单击并运行它时,测试通过。当您运行整个套件(包括此测试)时,此测试失败,并且只有此测试失败,表示只调用了一次函数 此测试没有要运行的安装或拆卸函数-只有模拟存储库和几行测试代码 当右键单击运行测试时,我可以调试它,并验证函数是否正确,是否确实调用了两次。但据我所知,我不能在调试模式下运行整个测试套件 我如何找出为什么这个测试在单次运行和套件运行中表现不同 编辑:代码。我正在验证SaveC

我有一个单元测试,它验证(使用Moq)一个特定函数被调用了多少次。应该叫两次

在VisualStudio中右键单击并运行它时,测试通过。当您运行整个套件(包括此测试)时,此测试失败,并且只有此测试失败,表示只调用了一次函数

此测试没有要运行的安装或拆卸函数-只有模拟存储库和几行测试代码

当右键单击运行测试时,我可以调试它,并验证函数是否正确,是否确实调用了两次。但据我所知,我不能在调试模式下运行整个测试套件

我如何找出为什么这个测试在单次运行和套件运行中表现不同

编辑:代码。我正在验证SaveChanges()方法

public override void SaveChanges()
{
bool isNew=CurrentCampaign.IsNewCampaign;
DocTreeViewModel.SaveChanges();//此方法发布在下面
使用(IRepository r=Rep.Renew())
{
foreach(在CurrentCampaign.Quotes中引用)
{
r、 更新(报价);
}
r、 SaveChanges();//在此处调用
}
如果(是新的)
{
CreateScheduleDocument();
}
}
//这是DocTreeViewModel.SaveChanges中的代码
公共覆盖无效保存更改()
{
使用(IRepository r=Rep.Renew())
{
//展平是展平递归树的扩展方法
foreach(DocumentCategories.flatte()中的DocumentCategories dc)
{
r、 更新(dc);
}
r、 SaveChanges();//在此处调用
}
}
//模拟设置
私有Mock GetMockRepository()
{
Mock repMock=新建Mock();
Setup(m=>m.Renew()).Returns(repMock.Object);
repMock.Setup(m=>m.Update(It.IsAny()).Verifiable();
repMock.Setup(m=>m.SaveChanges()).Verifiable();
ItemType it1=新的ItemType{ItemTypeId=1};
Setup(m=>m.GetItemTypes())。返回((新列表{it1}).AsQueryable);
返回repMock;
}
//试验
[测试方法]
public void Assert\u SignOff\u ChangesStatusEnum()
{
Mock repMock=GetMockRepository();
活动概览模型vm=新的活动概览模型(新的活动(),repMock.Object,新的Mock().Object);
vm.SignOff();//这将调用SaveChanges
Assert.AreEqual(活动状态.Signed,vm.CurrentCampaign.StatusEnum);
Verify(m=>m.SaveChanges(),Times.justice(2));
}

不确定您使用的是什么版本的VS,但您可以在2013年以调试模式运行测试套件。2013年是测试>调试>全部Tests@sign哦,太好了。谢谢-我不知道那里有。它运行了两次函数,但Moq声称它只运行了一次。发布代码后,可能是优化器的问题导致它在生产模式下只运行一次。这听起来像是模拟的范围问题,您应该在问题中包含一个。@sign-done,谢谢
public override void SaveChanges()
{
    bool isNew = CurrentCampaign.IsNewCampaign;
    DocTreeViewModel.SaveChanges(); //this method posted below

    using (IRepository r = Rep.Renew())
    {
        foreach (Quote quote in CurrentCampaign.Quotes)
        {
            r.Update(quote);
        }

        r.SaveChanges(); // called here
    }

    if (isNew)
    {
        CreateScheduleDocument();
    }
}

// this is the code in DocTreeViewModel.SaveChanges
public override void SaveChanges()
{
    using(IRepository r = Rep.Renew())
    {
        // Flatten is an extension method to flatten a recursive tree
        foreach(DocumentCategory dc in DocumentCategories.Flatten()) 
        {
            r.Update(dc);
        }

        r.SaveChanges(); //called here
    }
}

// mock setup
private Mock<IRepository> GetMockRepository()
{
    Mock<IRepository> repMock = new Mock<IRepository>();
    repMock.Setup(m => m.Renew()).Returns(repMock.Object);

    repMock.Setup(m => m.Update(It.IsAny<Campaign>())).Verifiable();

    repMock.Setup(m => m.SaveChanges()).Verifiable();

    ItemType it1 = new ItemType { ItemTypeId = 1 };
    repMock.Setup(m => m.GetItemTypes()).Returns((new List<ItemType> { it1 }).AsQueryable);

    return repMock;
}

//test
[TestMethod]
public void Assert_SignOff_ChangesStatusEnum()
{
    Mock<IRepository> repMock = GetMockRepository();
    CampaignOverviewViewModel vm = new CampaignOverviewViewModel(new Campaign(), repMock.Object, new Mock<IMsgBoxService>().Object);

    vm.SignOff(); //this calls SaveChanges
    Assert.AreEqual(CampaignStatus.Signed, vm.CurrentCampaign.StatusEnum);
    repMock.Verify(m => m.SaveChanges(), Times.Exactly(2));
}