【问题标题】:Mocking FormsIdentity.Ticket.UserData with Moq使用 Moq 模拟 FormsIdentity.Ticket.UserData
【发布时间】:2009-10-09 22:55:44
【问题描述】:

作为单元测试的一部分,我试图模拟 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 因为它是密封类的一部分

标签: asp.net-mvc tdd mocking moq


【解决方案1】:

无论如何,我都不是单元测试专家,只是在该区域弄湿了我的脚。

在单元测试中模拟身份是不是有点矫枉过正,因为身份代码是您可以假设已经独立工作的代码? (即,它是 Microsoft 的代码?)例如,当您对自己的代码进行单元测试时,您不需要模拟出其中一个 Framework 对象。我的意思是,您是否需要模拟列表或字典?

话虽如此,如果您真的想单独测试您的代码,或者出于某种原因对 Userdata 中返回的数据进行超级精细的控制,您就不能只为 Identity 和您的代码之间的交互编写一个接口吗?

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

希望对你有帮助

【讨论】:

  • 我试图让问题保持简洁是我的错。但这对我不起作用,因为在我尝试测试的方法中访问了 Principal 身份。但是你是对的,我没有测试我的方法的正确部分
猜你喜欢
  • 2011-06-13
  • 2019-09-11
  • 2010-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多