关于c#:ASP.NET MVC web项目中的单元测试类是一个很好的例子吗?

Are the unit test classes in ASP.NET MVC web project a good example?

我在学TDD。我知道依赖注入,通过它,您可以将类的依赖项放入构造函数的参数中,并让它们传入,从默认构造函数(例如)传入默认实现;

1
2
3
4
5
6
7
8
public AccountController() : this( RepositoryFactory.Users())
{
}

public AccountController( IUserRepository oUserRepository)
{
 m_oUserRepository = oUserRepository;
}

RepositoryFactory是一个简单的静态类,它返回为当前生成选择的实现

但是默认的ASP.NET MVC Web应用程序项目不这样做,而是DI采用公共属性的形式,这些公共属性是在测试类(例如,来自accountcontroller.cs)的对象初始值设定项中分配的:

1
2
3
4
5
6
7
8
9
protected override void Initialize(RequestContext requestContext)
{
 if (FormsService == null)
  { FormsService = new FormsAuthenticationService(); }
 if (MembershipService == null)
  { MembershipService = new AccountMembershipService(); }

 base.Initialize(requestContext);
}

在测试类accountcontrollertest.cs中:

1
2
3
4
5
6
7
8
9
10
private static AccountController GetAccountController()
{
 AccountController controller = new AccountController()
 {
  FormsService = new MockFormsAuthenticationService(),
  MembershipService = new MockMembershipService(),
  Url = new UrlHelper(requestContext),
 };
 //snip
}

所以现在我的accountController类有两种方法来进行依赖注入。我应该用哪一个?构造函数注入还是公共属性?

正在考虑构造函数注入…

ASP.NET MVC是否使用了这样的公共属性,因为您需要提供一种特定的注入到构造函数中的方法,而基本的"创建新的"Web应用程序需要是通用的作为起点?


ASP.NET MVC中的示例演示了如何不使用DI。

首先,使用默认构造函数和重载构造函数会引入歧义:类是控制自己的依赖项,还是从外部获取依赖项?显然,它不能真正决定。

其次,拥有默认实现会引入紧密耦合,因为在没有引用默认实现的情况下,无法创建该实现的新实例。然而,DI的全部目的是实现松耦合。

不幸的是,我们经常看到这个成语。在我的书中,我称之为"混蛋注射反模式";我从OrenEini/AyendeRahien的一篇固执己见的博客文章中取了这个名字,在那里他会遇到一个非常相似的例子。

作为一般建议,我建议在大多数情况下使用构造函数注入。它易于实现并且具有非常强的语义:它强制使用者提供依赖项的实例,有效地声明依赖项是强制的。

另一方面,属性注入意味着依赖项是可选的,因为编译器不会强制您赋值。在大多数情况下,依赖关系实际上不是可选的,因此很少使用这种模式。


看看结构图。您是正确的……构造函数注入是DI/IOC的首选方法。看看马丁·福勒的这篇文章。希望这对你有帮助。