Unit testing 为什么我的ViewModel不应该依赖于服务的具体实现?

Unit testing 为什么我的ViewModel不应该依赖于服务的具体实现?,unit-testing,mvvm,dependency-injection,mocking,Unit Testing,Mvvm,Dependency Injection,Mocking,我的ViewModel通常通过接口依赖于某些服务,DI容器将注入实际实现。因此,我可以为单元测试创建这些服务的模拟行为 public class MyViewModel { public MyViewModel(IMyService myService) { } } 但是我们有一些模拟框架,比如,您可以为您的服务的具体实现设置模拟行为,即使没有接口。这是否意味着ViewModels可以依赖于具体的服务类而不是接口?除了单元测试之外,拥有接口还有

我的ViewModel通常通过接口依赖于某些服务,DI容器将注入实际实现。因此,我可以为单元测试创建这些服务的模拟行为

public class MyViewModel 
{
        public MyViewModel(IMyService myService)
        {
        }
}

但是我们有一些模拟框架,比如,您可以为您的服务的具体实现设置模拟行为,即使没有接口。这是否意味着ViewModels可以依赖于具体的服务类而不是接口?除了单元测试之外,拥有接口还有其他用途吗?

一般的想法是拥有一个易于发展的项目。接口为您提供了较少的耦合,因为您可以有不同的实现,包括测试实现模拟。这就是理论

根据我的经验:如果您只有一个服务实现,并且可以轻松地对其进行模拟,那么只有一个没有接口的实现就足够了。如果将来需要另一个实现,您可以重构。但它仍然需要两件事

定义接口:您仍然需要明确定义服务提供的合同。所以你需要一些公开的方法,一些私有的方法。而且您的视图不能使用私有方法,否则进行任何更改都会困难得多 开发人员必须理解接口。如果您已经明确定义了接口,那么它就是一个很好的文档。如果您没有,那么您的团队可以更轻松地对其进行更改,使其开始使用本应作为内部服务实现的功能
总的想法是要有一个易于发展的项目。接口为您提供了较少的耦合,因为您可以有不同的实现,包括测试实现模拟。这就是理论

根据我的经验:如果您只有一个服务实现,并且可以轻松地对其进行模拟,那么只有一个没有接口的实现就足够了。如果将来需要另一个实现,您可以重构。但它仍然需要两件事

定义接口:您仍然需要明确定义服务提供的合同。所以你需要一些公开的方法,一些私有的方法。而且您的视图不能使用私有方法,否则进行任何更改都会困难得多 开发人员必须理解接口。如果您已经明确定义了接口,那么它就是一个很好的文档。如果您没有,那么您的团队可以更轻松地对其进行更改,使其开始使用本应作为内部服务实现的功能 但是我们有一些模拟框架,比如Moq,在这里,即使没有接口,您也可以为服务的具体实现设置模拟行为

不完全是。使用Moq,您只能模拟可以覆盖/实现的内容。在大多数情况下,这将是一个接口,但有时是一个具有虚拟/抽象方法的类

现在,若你们的服务将方法公开为虚拟的问题,为什么他们会这样做?当然,你可以使用最小起订量,并能够模仿他们。否则就不行了

传递接口的要点是依赖于抽象,而不是具体的实现。这是原则的D-

但是我们有一些模拟框架,比如Moq,在这里,即使没有接口,您也可以为服务的具体实现设置模拟行为

不完全是。使用Moq,您只能模拟可以覆盖/实现的内容。在大多数情况下,这将是一个接口,但有时是一个具有虚拟/抽象方法的类

现在,若你们的服务将方法公开为虚拟的问题,为什么他们会这样做?当然,你可以使用最小起订量,并能够模仿他们。否则就不行了


传递接口的要点是依赖于抽象,而不是具体的实现。这是D原则-。

事实上,不,不是。DIP是为了避免编译时依赖从高级组件到运行时依赖的低级组件,只依赖于在高级定义并在低级实现的抽象;它不需要DI,DI也不意味着遵循DIP。@Rogério:是的,这是我用更多的文字写的。你提出DI的观点是什么?我的观点是,问题是关于DI,而不是DIP。还有迪!=迪普。@Rogério:我在哪里写的DI==DIP?当问题只提到DI时,你通过谈论DIP暗示了这一点。事实上,不,不是。DIP是为了避免编译时依赖从高级组件到运行时依赖的低级组件,只依赖于在高级定义并在低级实现的抽象;它不需要DI,DI也不意味着遵循DIP。@Rogério:是的,这是我用更多的文字写的。你提出DI的观点是什么?我的观点是,问题是关于DI,而不是DIP。还有迪!=迪普。@Rogério:我在哪里 是DI==DIP吗?当问题只提到DI时,你通过谈论DIP暗示了这一点。