使用Moq模拟FormsIdentity.Ticket.UserData

cod*_*tte 6 tdd asp.net-mvc moq mocking

作为单元测试的一部分,我试图模拟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);
Run Code Online (Sandbox Code Playgroud)

我试图测试的代码看起来像这样:

FormsIdentity fIdentity = HttpContext.Current.User.Identity as FormsIdentity;
string userData = fIdentity.Ticket.UserData;
Run Code Online (Sandbox Code Playgroud)

我想在单元测试中做的就是伪造FormsIdentity.Ticket.UserData的返回值.但是当我在第一部分运行代码时,我在尝试模拟FormsIdentity时遇到错误.错误说mock的类型必须是接口,抽象类或非密封类.

我试图使用IIdentity而不是FormsIdentity(FormsIdentity是IIdentity的一个实现)但是IIdentity没有.Ticket.UserData.

那么如何编写此测试以便从FormsIdentity.Ticket.UserData获取值?

小智 0

无论如何,我不是单元测试专家,只是在该领域涉足一下。

在单元测试中模拟 Identity 是不是太过分了,因为 Identity 代码是您可以假设已经可以单独工作的代码?(即,它是 Microsoft 的代码?)例如,在对您自己的代码进行单元测试时,您不需要模拟 Framework 对象之一。我的意思是,您是否需要模拟列表或字典?

话虽这么说,如果您真的想单独测试您的代码,或者出于某种原因对 Userdata 中返回的数据有超精细的控制,您难道不能为身份和代码之间的交互编写一个接口吗?

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
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助