2017-06-14 34 views
0

摘要如何让Moq明白类型约束可以接受已验证的呼叫?

我目前正在写一些集成代码,这样我可以与会计系统进行交互。

有问题的会计系统是Acceo Acomba,使用其SDK转而成为分布式COM对象。

我写了一个泛型类,用于任何给定Acomba实体的通用存储库。

public abstract class AcombaRepository<TEntity, TNativeRepository> 
    where TEntity : class 
    where TNativeRepository : IBaseDataKey { 
    public AcombaRepository(TNativeRepository nativeRepository, IMapper entityMapper) { 
     // Guard clauses... 
     NativeRepository = nativeRepository; 
     this.entityMapper = entityMapper; 
    } 

    protected readonly TNativeRepository NativeRepository; 

    public TEntity Create(TEntity toCreate) { 
     NativeRepository.ReserveCardNumber(); // Insert 
     entityMapper.Map(toCreate, NativeRepository); // Assigning props 
     NativeRepository.AddCard(); // Save or commit to Acomba 
    } 
} 

IBaseDataKey

此接口用于在系统内任何给定的访问实体的基础实体。为了确保我可以访问它的基础知识,我将这种类型约束放在我的通用存储库上。

AcombaProductsRepository

这是测试下的代码,其实际使用的碱方法原样。

public class AcombaProductsRepository : AcombaRepository<MyProduct, IProduct022> { 
    public AcombaPRoductsRepository(IProduct022 nativeRepository, IMapper productMapper) 
     : base(nativeRepository, productMapper) { 
    } 
} 

单元测试

为了确保我的代码使用Acomba SDK充分创建Acomba底层数据存储中的一个新的实体,我确认的某些步骤严格遵守。

public class AcombaProductsRepositoryTests { 
    private readonly Mock<IProduct022> nativeRepositoryMock; 
    private readonly AcombaProductsRepsoitory sut; 

    public AcombaProductsRepositoryTests() { 
     nativeRepositoryMock = new Mock<IProduct022>(); 
     sut = new AcombaProductsRepository(nativeRepositoryMock.Object); 
    } 

    [Fact] 
    public void Create_Should_Reserve_A_Card_Number() { 
     var toCreate = new MyProduct(); 
     nativeRepositoryMock.Setup(r => r.ReserveCardNumber()).Verifiable(); 

     sut.Create(toCreate); 

     nativeRepositoryMock.Verify(r => r.ReserveCardNumber()); 
    } 
} 

这里,虽然界面IProduct022IBaseDataKey派生,起订量指出,预期调用

  • IProduct022.ReserveCardNumber

从未执行。此外,还规定,进行调用是

  • IBaseDataKey.ReserveCardNumber

对于单元测试本身的精髓,它实际上并不重要的进行调用是否要么,只要ReserveCardNumber被调用。

如何使此测试通过?


更多详情(编辑)

下面是来自测试结果的错误消息。 Test Result Error Message

照我看,起订量执行基IBaseDataKey类的调用而不是IProduct022衍生因为类型约束之一,我怀疑。

+0

提供可用于重现问题的[mcve]。目前没有足够的细节 – Nkosi

+0

另外,如果'nativeRepositoryMock.Setup()'已经是'.Verifiable()',那么assert期间所需要的全部内容就是'nativeRepositoryMock.Verify();'将验证所有可验证的设置。 – Nkosi

+0

@Nkosi感谢您的反馈。我知道'.Verify()'的事情,除了我想特别验证这个调用,因为我是单元测试。我想到了,因为我在整个测试中为不同的方法调用设置了我的模拟,所以我需要检查是否只执行了这个调用。 –

回答

0

是基于所提供的OP

public class AcombaProductsRepository : AcombaRepository<MyProduct, IProduct022> { 
    public AcombaProductsRepository(IProduct022 nativeRepository) 
     : base(nativeRepository) { 
    } 
} 

public abstract class AcombaRepository<TEntity, TNativeRepository> 
    where TEntity : class 
    where TNativeRepository : IBaseDataKey { 

    public AcombaRepository(TNativeRepository nativeRepository) { 
     NativeRepository = nativeRepository; 
    } 

    protected readonly TNativeRepository NativeRepository; 

    public TEntity Create(TEntity toCreate) { 
     NativeRepository.ReserveCardNumber(); // Insert 
     NativeRepository.AddCard(); // Save or commit to Acomba 
     return toCreate; 
    } 
} 

以下最小假设作了接口和用于实体的,因为它们没有在OP提供使用以下最小示例

public interface IBaseDataKey { 
    void ReserveCardNumber(); 
    void AddCard(); 
} 

public interface IProduct022 : IBaseDataKey { 

} 

public class MyProduct { 

} 

的以下测试行使基于OP提供和使用MSTest的信息和起订量

[TestClass] 
public class AcombaProductsRepositoryTests { 
    private readonly Mock<IProduct022> nativeRepositoryMock; 
    private readonly AcombaProductsRepository sut; 

    public AcombaProductsRepositoryTests() { 
     nativeRepositoryMock = new Mock<IProduct022>(); 
     sut = new AcombaProductsRepository(nativeRepositoryMock.Object); 
    } 

    [TestMethod] 
    public void _Create_Should_Reserve_A_Card_Number() { 
     //Arrange 
     var toCreate = new MyProduct(); 
     nativeRepositoryMock.Setup(r => r.ReserveCardNumber()).Verifiable(); 

     //Act 
     sut.Create(toCreate); 

     //Asert 
     nativeRepositoryMock.Verify(r => r.ReserveCardNumber()); 
    } 
} 
012的最新版本

锻炼时的测试毫无例外地通过了。

我建议对原始代码进行审查,因为目前提供的问题不具有可重现性。