使用Moq模拟FormsIdentity.Ticket.UserData

6
作为单元测试的一部分,我试图模拟FormsIdentity.Ticket.UserData的返回值。
以下方法不起作用,但它应该能够说明我的意图:
var principal = Mock<IPrincipal>();
var formsIdentity = Mock<FormsIdentity>();
formsIdentity.Setup(a => a.Ticket.UserData).Returns("aaa | bbb | ccc");
principal.Setup(b => b.Identity).Returns(formsIdentity.Object);

我正在尝试测试的代码大致如下:

FormsIdentity fIdentity = HttpContext.Current.User.Identity as FormsIdentity;
string userData = fIdentity.Ticket.UserData;

我在单元测试中想要假造FormsIdentity.Ticket.UserData的返回值。但是当我运行第一段代码时,尝试模拟FormsIdentity时出现错误。错误提示必须模拟接口、抽象类或非密封类。

我尝试使用IIdentity代替FormsIdentity(FormsIdentity是IIdentity的实现),但是IIdentity没有.Ticket.UserData属性。

那么我该如何编写这个测试,以便从FormsIdentity.Ticket.UserData获取一个值呢?


事实证明,我试图测试的方法做了太多的事情。它违反了单一职责原则,这使得测试变得困难。我已经重构了这个方法。至于最初的问题 - 看起来没有办法模拟FormsIdentity.Ticket.UserData,因为它是一个密封类的一部分。 - codette
1个回答

0

我并不是单元测试专家,只是在这个领域开始涉足。

在单元测试中模拟身份验证是否有点过度了?因为您可以假设身份验证代码已经在隔离环境中正常工作了(即它是微软的代码)。例如,在单元测试自己的代码时,您不需要模拟框架对象之一。我的意思是,您是否需要模拟列表或字典?

话虽如此,如果您真的想要在隔离环境中测试代码,或者由于某种原因需要对返回的用户数据进行超级精细的控制,那么您不能只是为身份验证和您的代码之间的交互编写一个接口吗?

Public Interface IIdentityUserData
   Readonly Property UserData As String
End Interface

Public Class RealIdentityWrapper 
 Implements IIdentityUserData

Private _identity as FormsIdentity
Public Sub New(identity as FormsIdentity)
    'the real version takes in the actual forms identity object
    _identity = identity
End Sub
Readonly Property UserData As String Implements IIDentityUserData.UserData
     If not _identity is nothing then
         Return _identity.Ticket.UserData
     End If
End Property
End Class

 'FAKE CLASS...use this instead of Mock
 Public Class FakeIdentityWrapper 
 Implements IIdentityUserData


 Readonly Property UserData As String Implements IIDentityUserData.UserData
     If not _identity is nothing then
          Return "whatever string you want"
     End If
 End Property
 End Class



'here's the code that you're trying to test...modified slightly
 Dim fIdentity As FormsIdentity= HttpContext.Current.User.Identity
 Dim identityUserData As IIdentityUserData

 identityUserData = 
 'TODO: Either the Real or Fake implementation. If testing, inject  the Fake implementation. If in production, inject the Real implementation

 Dim userData as String
 userData = identityUserData.UserData

希望这能有所帮助


我的错,试图保持问题简洁。但对我来说这行不通,因为我正在尝试测试的方法内部访问了主要身份。但您是正确的,我没有测试方法的正确部分。 - codette

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接