我有一个Module
我想用来缓存一些东西的东西。这很简单。我想回避,ConcurrentDictionary
因为它需要有保证的操作。
Public Module SchemaTableCache
Private lockObject As New Object
Private columnCache As New Dictionary(Of String, SortedSet(Of String))
<Extension>
Public Sub CacheSchemaTable(dataReader As IDataReader, name As String)
SyncLock lockObject
Dim rows As New List(Of DataRow)
If columnCache.ContainsKey(name) Then
Return
End If
rows = dataReader.GetSchemaTable().Rows.OfType(Of DataRow)().ToList()
columnCache.Add(name, New SortedSet(Of String)(rows.Select(Function(r) r.Field(Of String)("ColumnName"))))
End SyncLock
End Sub
<Extension>
Public Function HasColumn(name As String, column As String) As Boolean
SyncLock lockObject
Dim cols As New SortedSet(Of String)
If Not columnCache.TryGetValue(name, cols) Then
Return False
End If
Return cols.Contains(column)
End SyncLock
End Function
End Module
事情就是这样。我有一些单元测试来测试利用该HasColumn
功能的代码。我像这样设置这些测试:
dataReader.Setup(Function(x) x(field)).Returns(val)
' setup the schema table
Dim table As New DataTable()
table.Columns.Add("ColumnName", GetType(String))
If setupTable Then
table.Rows.Add(field)
End If
dataReader.Setup(Function(x) x.GetSchemaTable()) _
.Returns(table)
dataReader.Object.CacheSchemaTable("table")
然后他们测试这个功能:
Dim typeName = GetType(T).Name
Debug.WriteLine($"IDataReader_Value({schemaTableName}.{column})")
If Not schemaTableName.HasColumn(column) Then
Debug.WriteLine($"Could not find column {column}; returning default value.")
Return typeName.DefaultValue()
End If
Dim input = dr(column)
Debug.WriteLine($"Found column {column}; returning value {input}.")
Return Value(Of T)(input)
你可以在这里看到我点击该HasColumn
方法的地方。事情就是这样。如果我单独执行这些测试,它们会成功;但是,如果我执行整个测试集,它们就会失败。
显然这里存在线程安全问题,但我无法终生弄清楚我做错了什么。有人可以帮我看看我哪里出错了吗?
测试失败时的输出是:
Test Name: IDataReader_ValueBoolean
Test Outcome: Failed
Result Message: Assert.AreEqual failed. Expected:<True>. Actual:<False>.
Result StandardOutput:
Debug Trace:
IDataReader_Value(table.field)
Could not find column field; returning default value.
测试成功时的输出是:
Test Name: IDataReader_ValueBoolean
Test Outcome: Passed
Result StandardOutput:
Debug Trace:
IDataReader_Value(table.field)
Found column field; returning value True.