Moq框架Func <t,t> </t,t>

时间:2012-02-10 12:58:01

标签: c# unit-testing moq

我是Moq和TDD的新手,我想要做的是在存储库界面上设置方法。

这是全文。

我有一个名为Tenant的域实体类,其属性为BusinessIdentificationNumber

public class Tenant:EntityBase<Tenant>,IAggregateRoot
{
 ...
 public string BusinessIdentificationNumber {get;set;}
 ...
}

接下来,我有这个实体的存储库,接口就像

public interface IRepository<T>
{
 ...
 T FindBy(Func<T,bool> func);
 ...
}

问题出在哪里,我使用的域服务包含创建租户的规则,就像

public class TenantCreationService:ITenantCreationService
{
    public TenantCreationService(IRepository<Tenant> tenantRepository){...}

    public void CreateTenant(Tenant tenant)
    {
        //from here there is call to IRepository<Tenant>.FindBy(funcMethod);
    }
}

在我正在测试TenantCreationService的单元测试中,我模拟了传递给构造函数的存储库,但我想测试该功能:

  • 当具有BusinessIdentificationNumber的租户已存在于存储或会话中时,应将其返回。

所以我试图像

那样做
repositoryMock.Setup(x=>x.FindBy(It.Is<Tenant>(t=>t.BusinessIdentificationNumber
   == _tenantInTest.BusinessIdentificationNumber))).Returns(_tenantInTest) 

但它没有编译。你知道我想做什么吗?

编辑: 当我尝试编译下面的代码片段时

repositoryMock.Setup(e => e.FindBy(t => t.BusinessNumber == _validTenant.BusinessNumber)).Returns(
                _validTenant);

我得到例外

Unsupported expression: t => (t.BusinessNumber == value(DP.IPagac.UnitTests.DP.IPagac.Module.TenantManagement.TenantDomainServiceTests)._validTenant.BusinessNumber)

2 个答案:

答案 0 :(得分:6)

我认为你正在尝试的是这个(删除了一些无关的东西,例如创建了ITenent,因此可以动态模拟):

[TestFixture]
public class Test
{
    [Test]
    public void CreateTenentAlreadyExistsTest()
    {
        var tenentMock = new Mock<ITenant>();
        var repoMock = new Mock<IRepository<ITenant>>();

        tenentMock.Setup(t => t.BusinessIdentificationNumber).Returns("aNumber");

        repoMock.Setup(r => r.FindBy(It.Is<System.Func<ITenant, bool>>(func1 => func1.Invoke(tenentMock.Object)))).Returns(tenentMock.Object);

        var tenantCreationService = new TenantCreationService(repoMock.Object);

        tenantCreationService.CreateTenant(tenentMock.Object);

        tenentMock.VerifyAll();
        repoMock.VerifyAll();
    }
}

public interface ITenant
{
    string BusinessIdentificationNumber { get; set; }
}

public class Tenant : ITenant
{
    public string BusinessIdentificationNumber { get; set; }
}

public interface IRepository<T>
{
    T FindBy(System.Func<T, bool> func);
}

public class TenantCreationService : ITenantCreationService
{
    private readonly IRepository<ITenant> _tenantRepository;

    public TenantCreationService(IRepository<ITenant> tenantRepository)
    {
        _tenantRepository = tenantRepository;
    }

    public void CreateTenant(ITenant tenant)
    {
        var existingTenant =
            _tenantRepository.FindBy(t => t.BusinessIdentificationNumber == tenant.BusinessIdentificationNumber);

        if (existingTenant == null)
        {
            //do stuff
        }
    }
}

public interface ITenantCreationService
{
    void CreateTenant(ITenant tenant);
}

答案 1 :(得分:0)

“当具有BusinessIdentificationNumber的租户已经存在于存储或会话中时,应该返回它。” - 从这个测试描述中我理解你应该在存储库类中测试这种行为而不是在服务类

在服务的单元测试中,你不应该测试数据访问层我的意思是你的存储库, 您应该只验证调用存储库方法FindBy。 我建议创建从IRepository接口和基类Repostiry派生的ITenantRepositry。