0
我有一个Module
,我想用来缓存一些东西。这很简单。我想避开ConcurrentDictionary
,因为它需要有保证的操作。SyncLock不能在单元测试中工作
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.