2012-02-10 62 views
5

我是Moq和TDD的新手,我正在尝试做的就是在存储库接口上设置方法。Moq框架Func <T,T>

这是完整的故事。

我有一个名为租客与物业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) 
+0

您可以在你的问题的编译错误? – 2012-02-10 13:02:35

回答

6

我想你想的acheive是这样(去掉了一些东西是多余的,例如,创造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); 
} 
+0

是的,你用findby方法调用它。我认为你明白了iam试图做的事情,但是你的代码并没有在我身上编译。我得到了不受支持的异常t =>(t.BusinessNumber == value)。试图达到的目的是在与具有特定业务编号的租户一起调用findby时,应该返回特定租户(当然,为了进行测试)。 – Ivan 2012-02-10 13:43:31

+0

你有最新的MOQ吗?你使用的是什么版本的框架?上面的内容会逐字地在我的工作站上编译并通过测试。 – 2012-02-10 14:19:28

+0

对不起,我没有注意到你编辑后。现在它工作 – Ivan 2012-02-10 14:31:54

0

片断“当租客BusinessIdentificationNumber存储或会话已经存在,它应该被退回。” - 从这个测试描述我明白,你应该在存储库类中测试这种行为不在服务类

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

+0

但这是服务类中的商业行为。我只使用存储库从数据库中获取数据。整个测试被称为CreateTenant_TenantWithSameIdAlreadyExist_ShouldThrowException()[和关于实现细节的句子仅用于开发目的,没有意义在这里介绍你的业务]; iam没有测试版本库行为,但是我想用预定义的条件(BusinessID ==“123”)调用CreateMethod on服务(并且委托调用存储库)的方式来存储库,它应该返回创建的tenant testfixturesetup – Ivan 2012-02-10 13:26:11