2017-06-14 37 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的最新版本

鍛鍊時的測試毫無例外地通過了。

我建議對原始代碼進行審查,因爲目前提供的問題不具有可重現性。