我刚刚开始使用ASP.NET MVC而且我也是单元测试的新手:)到目前为止,非常好。
我有一个控制器操作,使用viewmodel设置索引视图。测试控制器动作是直截了当的,因为我可以在控制器的构造函数中传递假服务类,但我的viewmodel非常复杂并且在实例化时获取它自己的服务类。
代码应该让我更清楚,我希望......
控制器操作:
Function Index(ByVal id As Integer?) As ActionResult
Dim totalCount As Integer = 0
Dim selectedClient As Integer
If id Is Nothing Then
selectedClient = _portalClientService.GetFirstClient().ID
Else
selectedClient = id
End If
Dim users As MembershipUserCollection = _membershipService.GetUsersByClientId(selectedClient, 0, 1000, totalCount)
Return View(New UserListViewModel(users, selectedClient))
End Function
Viewmodel类:
Public Class UserListViewModel
Private _clientService As IPortalClientService
Public Sub New(ByVal users As MembershipUserCollection, ByVal selectedClient As Integer)
Me.New(users, selectedClient, Nothing)
End Sub
Public Sub New(ByVal users As MembershipUserCollection, ByVal selectedClient As Integer, ByVal clientService As IPortalClientService)
_users = users
_clientService = If(clientService, New PortalClientService)
_clients = New SelectList(_clientService.GetClients.OrderBy(Function(c) c.ClientName), "ID", "ClientName", selectedClient)
End Sub
Private _users As MembershipUserCollection
Public Property Users() As MembershipUserCollection
Get
Return _users
End Get
Set(ByVal value As MembershipUserCollection)
_users = value
End Set
End Property
Private _clients As SelectList
Public Property Clients() As SelectList
Get
Return _clients
End Get
Set(ByVal value As SelectList)
_clients = value
End Set
End Property
End Class
编辑:
在测试控制器操作时,如何让viewmodel使用假服务类?
我应该抛弃第一个构造函数并始终从控制器传递服务,还是有另一种方式?
干杯,
尼克
答案 0 :(得分:3)
我可能会分裂头发,但我会说你的模型更像是一个域模型而不是一个视图模型。删除对IPortalClientService
的依赖关系,或者至少不让模型自己实例化它。
我更喜欢将这些依赖项从视图中删除,然后再移到控制器上。
答案 1 :(得分:0)
实际上,这是我们在面向公众的API中一直使用的模式,并且演示了依赖注入的良好用法。我会在代码审查中通过这个,没有任何问题。
您的实现为用户提供了灵活创建对象的选项,并提供了可测试性。
唯一的“问题”是你的测试不能轻易覆盖第一个构造函数中的一行代码,但如果你有一个对代码覆盖率狂热的人 - 这通常本身就是一个问题,那么这只是一个问题。