我有一个存储库,它接收一个数据层作为参数和一个像这样的tenantID。 (代码简化)
public class MyRepsitory{
private readonly IDataAccess _dataAccess;
private readonly string _tenantID;
public MyRepsitory(IDataAccess dataAccess, string tenantID)
{
_dataAccess = dataAccess;
_tenantID = tenantID;
}
}
}
此存储库还有一个私有的方法GetClientsForTenantID
,这基本上是我的观点,因为每个方法都依赖于GetClientsForTenantID
,这不适合单元测试,因为我不能存根或模拟{{1}在我目前的设计中。
这是我目前GetClientsForTenantID
方法的当前签名。 GetClientsForTenantID
我希望存储库将其作为内部行为来处理,这就是它为私有的原因。我不希望它作为公共成员,因为它对其他开发人员来说是可变的,我的api不可靠。我可以把它变成虚拟的,这样Mocking Framework就可以代理它,但这也感觉不对。
它需要注入一些仅用于测试的假冒客户端,或其他东西......
这显示了我在代码中遇到的问题。 例如,我无法测试我的GetProducts() - 方法
private IEnumerable<string> GetClientsForTenant(string tenantID)
另一个想法是我注入public IEnumerable<Product> GetProducts(string someParameter){
var clients = GetClientsForTenant(this._tenantId);
//do some logic that needs to be tested
}
基本上是一个类,负责根据tenantID解析客户端。但是这也需要传入IDataAccess,并且会执行应该执行存储库的操作。
像这样:
ITenantStore
感觉也不对,因为TenantStore(IDataAccess dataAccess, string tenantID)
MyRepository(IDataAccess dataAccess, ITenantStore tenantStore)
到处都是......
你建议怎样解决这个问题?任何提示提示?
编辑:
感谢您的评论,IDataAccess
不在存储库中的GetClientsForTenant
上。
我的测试看起来像这样:
DataAccess
由于var mockMockData = new Mock<IDataAccess>();
mockMockData.Setup(x=>
x.ExecuteQuery(It.IsAny<IDictionary<string,object>>(),It.IsAny<string>()))
.Returns(
new List<Product>()
)
.Callback<IDictionary<string,object>>(
(parameters,sql)=>{
passedInParameters = parameters;
});
_repository = new MyRepository(mockMockData.Object,"fakeUser");
var list = _repository.GetProducts();
// Assert the parameters that get's passed into the ExecuteQuery Method because there happens some logic.
在Repository和private上,因此对模拟GetClientsForTenant
没有帮助。它只会使用IDataAccess
方法调用具有不同参数的DataAccess。
答案 0 :(得分:2)
+1关于zaitsman的评论。 您似乎已经有一个很好的接缝,允许单独测试MyRepository。
如果a)IDataAccess是一个接口,并且b)你的GetClientsForTenant方法在内部使用它,你可以提供一个假的IDataAccess,返回预先准备好的假冒客户端,你将能够完全测试MyRepository的逻辑而不暴露任何私有方法。
你的直觉就在这里。一般来说,你不应该暴露私人以便进行单元测试。这就是为什么你应该总是专注于测试公开可见的行为,而不是将测试代码绑定到内部实现,如果你试图伪造GetClientsForTenant方法,你会这样做。这将导致脆弱的测试,每次更改某些实现细节时都会破坏(比如在内部调用GetClientsForTenant以外的方法)。
更新:在上一次编辑中你提到: &#34;由于GetClientsForTenant在Repository和private上,因此对Mock IDataAccess没有帮助。它只会使用不同的参数调用DataAccess,但是来自MyRepository.GetClientsForTenant方法。&#34;
确切地说,这就是重点。您的测试不应该关心存储库的内部实现。是否调用GetClientsForTenant是无关紧要的。然而,重要的是您的存储库如何与其IDataAccess协作者进行通信。