使用序列化模拟程序集






2.60/5 (2投票s)
2004 年 10 月 17 日
3分钟阅读

28494

123
一种模拟复杂类的方法。
引言
在团队环境中工作时,诸如有限的许可证密钥、安全性或网络访问等因素可能会阻碍测试环境的创建。 在最近的一个项目中,我的要求之一是与现有的 .NET 组件进行交互。 现有的组件无法在我的异地办公环境中复制,并且现有的安全策略不允许网络访问。 代码编写和接口测试看起来非常困难。
在本文中,我将介绍一种我用来克服此问题的方法。 简而言之,我使用的方法是从接口查询(函数调用)中捕获输出,然后序列化结果,将其写入文件,并通过电子邮件发送到我的办公室。 稍后,当我在异地需要模拟原始组件时,我调用一个具有与原始组件相同的参数和接口的替代函数,并反序列化我存储的结果。
此方法允许我完全模拟特定测试的接口。 实际概念非常简单,并且结果在提供临时测试环境方面非常有效。
首先,快速浏览一下我希望模拟的类...
为了便于解释,我创建了一个具有复杂结果集的类。 实际的内部处理并不重要,事实上,对于这个例子来说,我是否可以查看内部工作原理并不重要。
Public Class clsMyResult
'clsMyResult is complex (output) class,
'the result am interested in emulating.
Public myDS As DataSet
Public strDesc As String
Public myCounter As Int16 = 0
End Class
Public Class clsOriginalClassIWishToEmulate
'this is the original class I wish to emulate -
'but I want to pretend I don't know
'(or have access to) the internal workings
Public Function MakeResult(ByVal newTables As Int16) As clsMyResult
Dim myResult As New clsMyResult
Dim localDS As New DataSet
For y As Int16 = 1 To newTables
Dim thisTable As New DataTable("table" & y)
thisTable.Columns.Add("tab:" & y & "-col")
Dim myDataRow As DataRow
For x As Int16 = 1 To 10
myDataRow = thisTable.NewRow
myDataRow(0) = "table:" & y & " row:" & x
thisTable.Rows.Add(myDataRow)
Next
localDS.Tables.Add(thisTable)
myResult.myCounter += 1
Next
myResult.myDS = localDS
myResult.strDesc = "There are " & myResult.myCounter & _
" tables in the dataset"
Return myResult
End Function
End Class
调用 clsOriginalClassIWishToEmulate.MakeResult
将生成一个包含已填充的 DataSet
、一个文本字符串以及 DataSet
中表数量的计数器的输出类。
捕获原始类的输出
这种仿真的第一步是访问原始类——例如在本地开发者计算机上,并针对它运行查询。
在我的例子中,我将创建原始类的一个实例,并调用我想要模拟的函数。 我将传递给函数 int16
值 10:myOriginalClass.MakeResult(10)
。
Private Sub Serialize_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
' I want to use clsOriginalClassIWishToEmulate but
' I cannot because of access restrictions
' First thing to do is to instantiate the class
' and the results I want to copy
Dim myOrginalClass As New clsOriginalClassIWishToEmulate
Dim myResult As clsMyResult
'myResult is the output of clsOriginalClassIWishToEmulate.
'Let's decide we want to emulate as close as possible
'the class which is fed a value of "10"
'Next, let's get the result value
myResult = myOrginalClass.MakeResult(10)
'define an file to write the result to...
Dim myStreamWriter As StreamWriter
myStreamWriter = New StreamWriter("myresult.xml")
'and serialize the class
Dim mySerializer As New XmlSerializer(GetType(clsMyResult))
mySerializer.Serialize(myStreamWriter, myResult)
myStreamWriter.Close()
End Sub
在函数返回值后,我将结果序列化为 XML 文件。 请注意,我需要知道响应的结构,此代码段才能工作。
模拟原始类接口
下一步需要创建一个与原始类具有相同参数的替代类。 此类打开存储的 XML 文件,并返回一个实际值(在本例中,对于“10”)。
Public Class clsEmulatedClass
Public Function MakeResult(ByVal newTables As Int16) As clsMyResult
'the point of this class is to mimic the original - but in this case
'will only mimic correct functions for input value "10"
Dim myResult As New clsMyResult
'setup the stream reader and xml serializetion object
Dim myStreamReader As StreamReader
Dim mySerializer As New XmlSerializer(GetType(clsMyResult))
'load the saved XML file
myStreamReader = New StreamReader("myresult.xml")
myResult = mySerializer.Deserialize(myStreamReader)
myStreamReader.Close()
Return myResult
End Function
End Class
使用新函数
新创建的函数将与原始函数的操作相同,对于我们已模拟的函数。 当然,返回的类仅对于特定的一组输入值才是正确的。
增强功能
此示例的进一步添加可能包括
- 存储多个输入的结果(模拟类可以从具有匹配输入值的示例中返回结果);
- 模拟属性;
- 复制原始类命名空间的相关方面。
结论
此处显示的方法允许创建模拟类。 当原始类由于安全性、网络或许可限制而不可用时,这尤其有用。 虽然该方法非常简单,但它可以允许创建原本不可能的开发和测试环境。
祝你好运,编程愉快!!