Подтвердить что ты не робот

В SpecFlow как я могу обмениваться данными между шагами/функциями?

У меня есть две функции, которые используют общий шаг "When", но имеют разные шаги "Then" в разных классах.

Как получить доступ, например, ActionResult от моего вызова контроллера MVC в шаге "Когда" на моих двух шагах "Далее"?

4b9b3361

Ответ 1

В SpecFlow 1.3 существует три метода:

  • статические элементы
  • ScenarioContext
  • ContextInjection

Комментарии:

  • статические члены очень прагматичны и в этом случае не так злы, как мы, как разработчики могли бы сначала подумать (нет нити или необходимости для насмешек/замены в определениях шагов)

  • См. ответ от @Si Keep в этом потоке

  • Если конструктору класса определения шага нужны аргументы, Specflow пытается ввести эти аргументы. Это можно использовать для ввода одного и того же контекста в несколько этапов.
    См. пример здесь: https://github.com/techtalk/SpecFlow/wiki/Context-Injection

Ответ 2

Используйте класс ScenarioContext, который является словарем, который является общим для всех этапов.

ScenarioContext.Current.Add("ActionResult", actionResult);
var actionResult = (ActionResult) ScenarioContext.Current["ActionResult"];

Ответ 3

У меня есть вспомогательный класс, который позволяет мне писать

Current<Page>.Value = pageObject;

который является оберткой над ScenarioContext. Он работает от имени типа, поэтому его нужно немного расширить, если вам нужен доступ к двум переменным одного типа

 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 в настоящее время, похоже, вы получаете те же преимущества без необходимости определять расширение

Ответ 4

Мне не нравилось использовать Scenario.Context из-за необходимости отбрасывать каждую словарную запись. Я нашел другой способ хранения и извлечения предмета без необходимости разыгрывать его. Однако здесь есть компромисс, потому что вы эффективно используете тип в качестве ключа для доступа к объекту из словаря ScenarioContext. Это означает, что может быть сохранен только один элемент этого типа.

TestPage testPageIn = new TestPage(_driver);
ScenarioContext.Current.Set<TestPage>(testPageIn);
var testPageOut = ScenarioContext.Current.Get<TestPage>();

Ответ 5

Вы можете определить параметр в своих шагах, который является ключом к значению, которое вы храните. Таким образом, вы можете ссылаться на него в ваших последующих шагах, используя ключ.

...
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 

Вы можете сохранить фактическое значение в словаре или в наборе свойств или подобном.