Unit testing 我如何根据具体类型限制最低起订量期望值?

Unit testing 我如何根据具体类型限制最低起订量期望值?,unit-testing,moq,Unit Testing,Moq,我需要断言一个baseWorkItem传递给一个方法一次,而派生的sendmailworkitem传递一次 repo = new Mock<IWorkItemRepository>(); repo.Setup(x => x.Add(It.IsAny<WorkItem>())).Verifiable(); repo.Setup(x => x.Add(It.Is<SendEmailWorkItem>(wi => wi.ResponsibleId

我需要断言一个base
WorkItem
传递给一个方法一次,而派生的
sendmailworkitem
传递一次

repo = new Mock<IWorkItemRepository>();
repo.Setup(x => x.Add(It.IsAny<WorkItem>())).Verifiable();
repo.Setup(x => x.Add(It.Is<SendEmailWorkItem>(wi => wi.ResponsibleId == responsibleGuid))).Verifiable();
repo=newmock();
repo.Setup(x=>x.Add(It.IsAny()).Verifiable();
repo.Setup(x=>x.Add(It.Is(wi=>wi.ResponsibleId==responsibleGuid)).Verifiable();
莫克说,第一个预期发生两次,第二个预期发生0次。我理解这是因为类型在同一继承层次结构中。(以下断言采用MSpec语法)

它应该添加新的声明工作项=()=>repo.Verify(x=>x.add(MockIt.IsAny()),Times.Once());
它应该添加与新声明相同的安全服务通知工作项,并进行repo.Verify(x=>x.add(MockIt.Is(wi=>wi.ResponsibleId==responsibleGuid)),Times.Once();

如何根据类型限制期望值?

使用这种设置:

public interface IWorkItemRepository
{
    void Add(WorkItem workItem);
    IQueryable<WorkItem> GetAll();
    void Finish(int workitemId);
}

public class WorkItem
{
    public int Id { get; set; }
    public string Name { get; set; }        
}

public class SendEmailWorkItem : WorkItem
{
    public Guid ResponsibleId { get; set; }
}
公共接口IWorkItemRepository
{
无效添加(工作项工作项);
IQueryable GetAll();
无效完成(int workitemId);
}
公共类工作项目
{
公共int Id{get;set;}
公共字符串名称{get;set;}
}
公共类SendEmailWorkItem:WorkItem
{
公共Guid ResponsibleId{get;set;}
}
这会起作用,但可能不是最优雅的解决方案

[TestFixture]
public class WorkItemRepositoryTests
{
    [Test]
    public void Test()
    {
        // Arrange
        var responsibleGuid = new Guid("11111111-2222-3333-4444-555555555555");
        var workitemRepo = new Mock<IWorkItemRepository>();
        workitemRepo.Setup(x => x.Add(It.IsAny<WorkItem>())).Verifiable();
        workitemRepo.Setup(x => x.Add(It.Is<SendEmailWorkItem>(wi => wi.ResponsibleId == responsibleGuid))).Verifiable();

        // Act   
        workitemRepo.Object.Add(new WorkItem() {Id = 1});
        workitemRepo.Object.Add(new SendEmailWorkItem(){ResponsibleId = responsibleGuid});

        // Assert
        workitemRepo.Verify(x => x.Add(It.Is<WorkItem>(item => item.Id == 1 )), Times.Once());
        workitemRepo.Verify(x => x.Add(It.Is<SendEmailWorkItem>(wi => wi.ResponsibleId == responsibleGuid)), Times.Once());            
    }
[TestFixture]
公共类WorkItemRepositoryTests
{
[测试]
公开无效测试()
{
//安排
var responsibleGuid=新Guid(“11111111-2222-3333-4444-5555”);
var workitemRepo=new Mock();
workitemRepo.Setup(x=>x.Add(It.IsAny()).Verifiable();
workitemRepo.Setup(x=>x.Add(It.Is(wi=>wi.ResponsibleId==responsibleGuid)).Verifiable();
//表演
添加(新工作项(){Id=1});
添加(新的SendEmailWorkItem(){ResponsibleId=responsibleGuid});
//断言
workitemRepo.Verify(x=>x.Add(It.Is(item=>item.Id==1)),Times.Once();
workitemRepo.Verify(x=>x.Add(It.Is(wi=>wi.ResponsibleId==responsibleGuid)),Times.Once();
}
}

使用
It.Is
并检查类型:

namespace MoqTests
{
    using Moq;
    using NUnit.Framework;

    public class WorkItem
    {
        public int Id { get; set; }
    }

    public class SendEmailWorkItem : WorkItem
    {
        public string ResponsibleId { get; set; }
    }

    public interface IWorkItemRepository
    {
        void Add(WorkItem workItem);
    }

    public class Worker
    {
        private readonly IWorkItemRepository repository;

        public Worker(IWorkItemRepository repository)
        {
            this.repository = repository;
        }

        public void DoWork()
        {
            var workItem = new WorkItem{Id = 1};
            repository.Add(workItem);

            var emailWorkItem = new SendEmailWorkItem{Id = 2, ResponsibleId = "responsible"};
            repository.Add(emailWorkItem);
        }
    }

    [TestFixture]
    public class MoqTest
    {
        [Test]
        public void Should_add_WorkItem_and_SendEmailWorkItem()
        {
            //arrange
            var repository = new Mock<IWorkItemRepository>(MockBehavior.Strict);
            repository.Setup(r=>r.Add(It.Is<WorkItem>(item => item.GetType() == typeof(WorkItem)))).Verifiable();
            repository.Setup(r=>r.Add(It.Is<SendEmailWorkItem>(item=>item.ResponsibleId == "responsible"))).Verifiable();
            var worker = new Worker(repository.Object);

            //act
            worker.DoWork();

            //assert
            repository.Verify(r => r.Add(It.Is<WorkItem>(item => item.GetType() == typeof(WorkItem))), Times.Once());
            repository.VerifyAll();
        }
    }
} 
名称空间MoqTests
{
使用最小起订量;
使用NUnit.Framework;
公共类工作项目
{
公共int Id{get;set;}
}
公共类SendEmailWorkItem:WorkItem
{
公共字符串ResponsibleId{get;set;}
}
公共接口IWorkItemRepository
{
无效添加(工作项工作项);
}
公社工人
{
专用只读IWorkItemRepository存储库;
公共工作者(IWorkItemRepository)
{
this.repository=存储库;
}
公共工作
{
var workItem=newworkitem{Id=1};
添加(工作项);
var emailWorkItem=new sendmailworkitem{Id=2,ResponsibleId=“responsible”};
添加(emailWorkItem);
}
}
[测试夹具]
公共类MoqTest
{
[测试]
public void应添加工作项和SendEmailWorkItem()
{
//安排
var repository=newmock(MockBehavior.Strict);
repository.Setup(r=>r.Add(It.Is(item=>item.GetType()==typeof(WorkItem))).Verifiable();
repository.Setup(r=>r.Add(It.Is(item=>item.ResponsibleId==“responsible”)).Verifiable();
var worker=新的worker(repository.Object);
//表演
工人。道工();
//断言
Verify(r=>r.Add(It.Is(item=>item.GetType()==typeof(WorkItem)))、Times.Once();
repository.VerifyAll();
}
}
} 

以相反的顺序指定设置?

很遗憾,我不能-我的repo.Add调用在另一个类的方法中,而我在测试中调用的这个方法为什么在这里设置(…).verifyable()和Verify()在末尾?验证是否足够?使用相反的顺序没有帮助-它仍然会命中基类的设置2次。结果是:
namespace MoqTests
{
    using Moq;
    using NUnit.Framework;

    public class WorkItem
    {
        public int Id { get; set; }
    }

    public class SendEmailWorkItem : WorkItem
    {
        public string ResponsibleId { get; set; }
    }

    public interface IWorkItemRepository
    {
        void Add(WorkItem workItem);
    }

    public class Worker
    {
        private readonly IWorkItemRepository repository;

        public Worker(IWorkItemRepository repository)
        {
            this.repository = repository;
        }

        public void DoWork()
        {
            var workItem = new WorkItem{Id = 1};
            repository.Add(workItem);

            var emailWorkItem = new SendEmailWorkItem{Id = 2, ResponsibleId = "responsible"};
            repository.Add(emailWorkItem);
        }
    }

    [TestFixture]
    public class MoqTest
    {
        [Test]
        public void Should_add_WorkItem_and_SendEmailWorkItem()
        {
            //arrange
            var repository = new Mock<IWorkItemRepository>(MockBehavior.Strict);
            repository.Setup(r=>r.Add(It.Is<WorkItem>(item => item.GetType() == typeof(WorkItem)))).Verifiable();
            repository.Setup(r=>r.Add(It.Is<SendEmailWorkItem>(item=>item.ResponsibleId == "responsible"))).Verifiable();
            var worker = new Worker(repository.Object);

            //act
            worker.DoWork();

            //assert
            repository.Verify(r => r.Add(It.Is<WorkItem>(item => item.GetType() == typeof(WorkItem))), Times.Once());
            repository.VerifyAll();
        }
    }
}