ScenarioContext.当前线程安全
本文关键字:安全 线程 前线 ScenarioContext | 更新日期: 2023-09-27 18:15:25
我得到的印象是它不是。我有三个单独运行时成功的集成测试,但当并行运行时,我得到System.ArgumentException: An item with the same key has already been added.
我肯定希望ScenarioContext.Current
总是指正确的场景,但它似乎变得混乱。有人成功地为这个类添加了线程安全吗?或者我应该使用另一种方法来在步骤文件之间共享值?
场景上下文。颇来源:
public static ScenarioContext Current
{
get
{
if (current == null)
{
Debug.WriteLine("Accessing NULL ScenarioContext");
}
return current;
}
internal set { current = value; }
}
如你所见,它不是线程安全的https://github.com/techtalk/SpecFlow/blob/master/Runtime/ScenarioContext.cs 这似乎在SpecFlow V2中处理得更好:http://www.specflow.org/documentation/Parallel-Execution/
提取(更简单的选项):
[Binding]
public class StepsWithScenarioContext : Steps
{
[Given(@"I put something into the context")]
public void GivenIPutSomethingIntoTheContext()
{
this.ScenarioContext.Set("test-value", "test-key");
}
}
我知道这是一个旧的帖子,但它是很好的参考,所以这是我的解决方案:
将场景上下文替换为如下的自定义实现:
public class ScenarioContextSafe
{
private static ScenarioContextSafe _current;
private static readonly object Locker = new object();
public static ScenarioContextSafe Current
{
get
{
lock (Locker) {
return _current ?? (_current = new ScenarioContextSafe());
}
}
}
public static void Reset()
{
lock (Locker) {
_current = null;
}
}
private readonly ConcurrentDictionary<string, object> _concurrentDictionary = new ConcurrentDictionary<string, object>();
public void Add(string key, object value)
{
_concurrentDictionary.TryAdd(key, value);
}
public void Set(object value, string key)
{
if (!_concurrentDictionary.ContainsKey(key))
_concurrentDictionary.TryAdd(key, value);
else
_concurrentDictionary[key] = value;
}
public void Remove(string key)
{
object result;
_concurrentDictionary.TryRemove(key, out result);
}
public T Get<T>(string key)
{
object result;
_concurrentDictionary.TryGetValue(key, out result);
return (T)result;
}
public bool ContainsKey(string key)
{
return _concurrentDictionary.ContainsKey(key);
}
public void Pending()
{
ScenarioContext.Current.Pending();
}
public ScenarioInfo ScenarioInfo{
get { return ScenarioContext.Current.ScenarioInfo; }
}
}
然后,在每个场景之前创建一个钩子来重置上下文
[BeforeScenario()]
public static void BeforeAllScenario()
{
ScenarioContextSafe.Reset();
}