2011-11-02 62 views
3

我对要测试的对象有相当重要的依赖关系图。解决我的依赖问题最简单的方法是什么,而无需在任何地方注册mocks?在大型依赖对象图上注入模拟

例如,我有一个依赖关系图如下:

PublicApi 
    ApiService 
     AccountingFacade 
     BillingService 
      BillingValidation 
      BillingRepository 
     UserService 
      UserRepository 

我想测试PublicApi.CreateUser(),我希望它通过所有的代码运行,但我想嘲笑仓库所以我不不得不向数据库写入任何内容。我应该只使用一个DI容器并注册我的所有服务,并使用mock替换存储库,然后解析PublicApi并运行该方法?

我正在研究AutoFixture,看起来它可能能够处理这样的事情,但我无法将自己的头围绕整个'Freeze'与'Register'并且它与Moq集成。

回答

5

对于Unittests,您应该只模拟直接依赖关系。在你的情况下,你创建PublicApi并为ApiService注入一个模拟,并验证PublicApi是否在ApiService模拟上使用正确的值调用适当的方法。

以同样的方式测试所有其他与更深层依赖关系隔离的组件。

如果你想测试几个组件的组合,那不是单元测试,而是集成测试。因此,这取决于你如何将你的课程放在一起。例如如果您使用的是IoC容器,则可能支持以某种方式替换存储库的配置。在这种情况下,您可以使用应用程序的配置并使用mock替换存储库以及潜在的视图。

+0

这是有道理的。我可以通过进行多层测试来获得全面覆盖,而不是一次测试多个层。 – scottm

+0

确切地说,它使得测试本身更简单,更易于理解。 –

+0

+1,直接点。 –

1

这可能没有什么帮助,但我会说无论如何。

看来你试图一次测试太多,为什么不只是测试BillingService-> BillingValidation,然后是BillingService-> BillingRepository等。这样你将有一套测试证明每个测试都能正常工作,那么当你在PublicApi Layer上,你只需要模拟ApiService,因为你已经测试了它下面的所有东西,所以再次测试它没有任何价值。

一般我只会一次测试1层,但我不知道你的完整场景,所以你可能有些东西我没有考虑到,所以如果是这种情况,你真的需要测试所有这一切我只会带入一个简单轻量级的DI框架,比如Ninject或其他东西。

这样你就可以将所有的类型绑定到mock上,然后从你的PublicApi上实例化。

随着ninject它看起来是这样的:

Kernel.Bind<UserRepository>.ToConst(YourMockUserRepositoryInstance); 
Kernel.Bind<UserService>.ToConst(YourMockUserServiceInstance); 
Kernel.Bind<BillingRepository>.ToConst(YourMockBillingRepositoryInstance); 
Kernel.Bind<BillingValidation>.ToConst(YourMockBillingValidationInstance); 
Kernel.Bind<BillingService>.ToConst(YourMockBillingServiceInstance); 
Kernel.Bind<AccountingFacade>.ToConst(YourMockAccountingFacadeInstance); 
Kernel.Bind<ApiService>.ToConst(YourMockApiServiceInstance); 
Kernel.Bind<PublicApi>.ToSelf(); 

var publicApi = Kernel.Get<PublicApi>(); 

虽然你要问自己,你在这里的测试?如果我只是首先提到它,我会这样做,如果它更多的话可能会考虑后者的选择。无论哪种方式,我希望它给你一些选择。