共通の「When」ステップを使用するが、異なるクラスで異なる「Then」ステップを持つ2つの機能があります。
たとえば、2つのThenステップのWhenステップでMVCコントローラー呼び出しからActionResultにアクセスするにはどうすればよいですか?
SpecFlow 1.3には、次の3つの方法があります。
コメント:
静的メンバーは非常に実用的であり、この場合、開発者が最初に考えるほど邪悪ではありません(ステップ定義でのスレッド化やモック/置換の必要はありません)
このスレッドで@SiKeepからの回答を参照してください
ステップ定義クラスのコンストラクターに引数が必要な場合、Specflowはこれらの引数を挿入しようとします。これを使用して、同じコンテキストを複数のステップ定義に挿入できます。
こちらの例をご覧ください: https ://docs.specflow.org/projects/specflow/en/latest/Bindings/Context-Injection.html
すべてのステップに共通の辞書であるScenarioContextクラスを使用します。
ScenarioContext.Current.Add("ActionResult", actionResult);
var actionResult = (ActionResult) ScenarioContext.Current["ActionResult"];
書くことができるヘルパークラスがあります
Current<Page>.Value = pageObject;
これはScenarioContextのラッパーです。タイプ名で機能するため、同じタイプの2つの変数にアクセスする必要がある場合は、少し拡張する必要があります。
public static class Current<T> where T : class
{
internal static T Value
{
get {
return ScenarioContext.Current.ContainsKey(typeof(T).FullName)
? ScenarioContext.Current[typeof(T).FullName] as T : null;
}
set { ScenarioContext.Current[typeof(T).FullName] = value; }
}
}
2019年の編集:最近は@JoeTの回答を使用しますが、拡張機能を定義しなくても同じメリットが得られるようです
各辞書エントリをキャストする必要があるため、Scenario.Contextを使用するのは好きではありませんでした。キャストせずにアイテムを保存および取得する別の方法を見つけました。ただし、ScenarioContextディクショナリからオブジェクトにアクセスするキーとしてタイプを効果的に使用しているため、ここではトレードオフがあります。これは、そのタイプのアイテムを1つだけ保存できることを意味します。
TestPage testPageIn = new TestPage(_driver);
ScenarioContext.Current.Set<TestPage>(testPageIn);
var testPageOut = ScenarioContext.Current.Get<TestPage>();
保存する値の鍵となるパラメーターをステップで定義できます。このようにして、キーを使用して後の手順で参照できます。
...
Then I remember the ticket number '<MyKey>'
....
When I type my ticket number '<MyKey>' into the search box
Then I should see my ticket number '<MyKey>' in the results
実際の値を辞書やプロパティバッグなどに保存できます。
これはGoogleで私が思いついた最初の結果なので、@jbandiの答えが最も完全であると言っておきたいと思いました。ただし、バージョン3.0以降では次のようになります。
SpecFlow 3.0では、ScenarioContext.CurrentとFeatureContext.Currentを廃止としてマークし、将来これらのプロパティを使用しないようにする必要があることを明確にしました。これらのプロパティから離れる理由は、シナリオを並行して実行している場合は機能しないためです。
(SpecFlow 3.0以降のScenarioContextおよびFeatureContext)
したがって、テスト中にデータを保存する最新の方法は、コンテキストインジェクションを使用することです。サンプルコードを追加しますが、実際にはリンクのサンプルコードは優れているので、チェックしてください。
バインディングクラスにインスタンスを挿入することで、現在は廃止されているScenarioContext.Currentを模倣できます。
[Binding]
public class MyStepDefs
{
private readonly ScenarioContext _scenarioContext;
public MyStepDefs(ScenarioContext scenarioContext)
{
_scenarioContext= scenarioContext ;
}
public SomeMethod()
{
_scenarioContext.Add("key", "value");
var someObjectInstance = new SomeObject();
_scenarioContext.Set<SomeObject>(someObjectInstance);
_scenarioContext.Get<SomeObject>();
// etc.
}
}