From f6fcb089ee9315115256aeecaa7e18af65a8c766 Mon Sep 17 00:00:00 2001 From: Mark Hoek Date: Wed, 30 Oct 2019 21:09:52 +0100 Subject: [PATCH] Add test for Context Injection Scope (#13) Example for issue #12 --- .../ContextInjectionScope.feature | 17 +++ .../ContextInjectionScope.feature.cs | 140 ++++++++++++++++++ .../ContextInjectionScopeSteps.cs | 75 ++++++++++ .../SpecFlow.DependencyInjection.Tests.csproj | 9 ++ .../TestDependencies.cs | 3 + 5 files changed, 244 insertions(+) create mode 100644 SpecFlow.DependencyInjection.Tests/ContextInjectionScope.feature create mode 100644 SpecFlow.DependencyInjection.Tests/ContextInjectionScope.feature.cs create mode 100644 SpecFlow.DependencyInjection.Tests/ContextInjectionScopeSteps.cs diff --git a/SpecFlow.DependencyInjection.Tests/ContextInjectionScope.feature b/SpecFlow.DependencyInjection.Tests/ContextInjectionScope.feature new file mode 100644 index 0000000..1a98263 --- /dev/null +++ b/SpecFlow.DependencyInjection.Tests/ContextInjectionScope.feature @@ -0,0 +1,17 @@ +Feature: ContextInjectionScope + Issue #12: Scoping Context Injection to Scenario Execution Lifetimes + https://github.com/solidtoken/SpecFlow.DependencyInjection/issues/12 + +Scenario: Assert Context Is Scoped To Scenario Execution + The multiply and increase steps are intentionally implemented using different bindings. + Assert that they can operate on the same context (within the scenario executing). + Given I have test context with number 5 + When I multiply the test context number by 2 + And I increase the test context number by 3 + Then the test context number should be 13 + +Scenario: Assert Context Is Scoped To Scenario Execution (No Spill) + Assert that the test context does not spill over to other scenarios. + Note that this assumes this scenario will be run after the above one (ie don't use parallel tests). + Given I have a test context + Then the test context number should be 0 diff --git a/SpecFlow.DependencyInjection.Tests/ContextInjectionScope.feature.cs b/SpecFlow.DependencyInjection.Tests/ContextInjectionScope.feature.cs new file mode 100644 index 0000000..e25dcab --- /dev/null +++ b/SpecFlow.DependencyInjection.Tests/ContextInjectionScope.feature.cs @@ -0,0 +1,140 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by SpecFlow (http://www.specflow.org/). +// SpecFlow Version:3.0.0.0 +// SpecFlow Generator Version:3.0.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +#region Designer generated code +#pragma warning disable +namespace SolidToken.SpecFlow.DependencyInjection.Tests +{ + using TechTalk.SpecFlow; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.0.0.0")] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public partial class ContextInjectionScopeFeature : Xunit.IClassFixture, System.IDisposable + { + + private static TechTalk.SpecFlow.ITestRunner testRunner; + + private Xunit.Abstractions.ITestOutputHelper _testOutputHelper; + +#line 1 "ContextInjectionScope.feature" +#line hidden + + public ContextInjectionScopeFeature(ContextInjectionScopeFeature.FixtureData fixtureData, Xunit.Abstractions.ITestOutputHelper testOutputHelper) + { + this._testOutputHelper = testOutputHelper; + this.TestInitialize(); + } + + public static void FeatureSetup() + { + testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "ContextInjectionScope", " Issue #12: Scoping Context Injection to Scenario Execution Lifetimes\r\n htt" + + "ps://github.com/solidtoken/SpecFlow.DependencyInjection/issues/12", ProgrammingLanguage.CSharp, ((string[])(null))); + testRunner.OnFeatureStart(featureInfo); + } + + public static void FeatureTearDown() + { + testRunner.OnFeatureEnd(); + testRunner = null; + } + + public virtual void TestInitialize() + { + } + + public virtual void ScenarioTearDown() + { + testRunner.OnScenarioEnd(); + } + + public virtual void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + { + testRunner.OnScenarioInitialize(scenarioInfo); + testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(_testOutputHelper); + } + + public virtual void ScenarioStart() + { + testRunner.OnScenarioStart(); + } + + public virtual void ScenarioCleanup() + { + testRunner.CollectScenarioErrors(); + } + + void System.IDisposable.Dispose() + { + this.ScenarioTearDown(); + } + + [Xunit.FactAttribute(DisplayName="Assert Context Is Scoped To Scenario Execution")] + [Xunit.TraitAttribute("FeatureTitle", "ContextInjectionScope")] + [Xunit.TraitAttribute("Description", "Assert Context Is Scoped To Scenario Execution")] + public virtual void AssertContextIsScopedToScenarioExecution() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Assert Context Is Scoped To Scenario Execution", " The multiply and increase steps are intentionally implemented using different" + + " bindings.\r\n Assert that they can operate on the same context (within the sce" + + "nario executing).", ((string[])(null))); +#line 5 +this.ScenarioInitialize(scenarioInfo); + this.ScenarioStart(); +#line 8 + testRunner.Given("I have test context with number 5", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line 9 + testRunner.When("I multiply the test context number by 2", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line 10 + testRunner.And("I increase the test context number by 3", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line 11 + testRunner.Then("the test context number should be 13", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + this.ScenarioCleanup(); + } + + [Xunit.FactAttribute(DisplayName="Assert Context Is Scoped To Scenario Execution (No Spill)")] + [Xunit.TraitAttribute("FeatureTitle", "ContextInjectionScope")] + [Xunit.TraitAttribute("Description", "Assert Context Is Scoped To Scenario Execution (No Spill)")] + public virtual void AssertContextIsScopedToScenarioExecutionNoSpill() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Assert Context Is Scoped To Scenario Execution (No Spill)", " Assert that the test context does not spill over to other scenarios.\r\n Not" + + "e that this assumes this scenario will be run after the above one (ie don\'t use " + + "parallel tests).", ((string[])(null))); +#line 13 +this.ScenarioInitialize(scenarioInfo); + this.ScenarioStart(); +#line 16 + testRunner.Given("I have a test context", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line 17 + testRunner.Then("the test context number should be 0", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + this.ScenarioCleanup(); + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.0.0.0")] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class FixtureData : System.IDisposable + { + + public FixtureData() + { + ContextInjectionScopeFeature.FeatureSetup(); + } + + void System.IDisposable.Dispose() + { + ContextInjectionScopeFeature.FeatureTearDown(); + } + } + } +} +#pragma warning restore +#endregion diff --git a/SpecFlow.DependencyInjection.Tests/ContextInjectionScopeSteps.cs b/SpecFlow.DependencyInjection.Tests/ContextInjectionScopeSteps.cs new file mode 100644 index 0000000..8c0fed8 --- /dev/null +++ b/SpecFlow.DependencyInjection.Tests/ContextInjectionScopeSteps.cs @@ -0,0 +1,75 @@ +using System; +using System.Diagnostics; +using TechTalk.SpecFlow; +using Xunit; + +namespace SolidToken.SpecFlow.DependencyInjection.Tests +{ + public class TestContext + { + public int Number { get; set; } + } + + [Binding] + public class ContextInjectionScopeSteps + { + private readonly TestContext _context; + + public ContextInjectionScopeSteps(TestContext context) + { + _context = context; + } + + [Given(@"I have a test context")] + public void GivenIHaveATestContext() + { + // NOOP + } + + [Given(@"I have test context with number (.*)")] + public void GivenIHaveTestContextWithNumber(int number) + { + _context.Number = number; + } + + [Then(@"the test context number should be (.*)")] + public void ThenTheTestContextNumberShouldBe(int expected) + { + Assert.Equal(expected, _context.Number); + } + } + + [Binding] + public class MultiplySteps + { + private readonly TestContext _context; + + public MultiplySteps(TestContext context) + { + _context = context; + } + + [When(@"I multiply the test context number by (.*)")] + public void WhenIMultiplyTheTestContextNumberBy(int multiply) + { + _context.Number *= multiply; + } + } + + [Binding] + public class IncreaseSteps + { + private readonly TestContext _context; + + public IncreaseSteps(TestContext context) + { + _context = context; + } + + [When(@"I increase the test context number by (.*)")] + public void WhenIIncreaseTheTestContextNumberBy(int increase) + { + _context.Number += increase; + } + } +} diff --git a/SpecFlow.DependencyInjection.Tests/SpecFlow.DependencyInjection.Tests.csproj b/SpecFlow.DependencyInjection.Tests/SpecFlow.DependencyInjection.Tests.csproj index 6e4eb73..a94aa90 100644 --- a/SpecFlow.DependencyInjection.Tests/SpecFlow.DependencyInjection.Tests.csproj +++ b/SpecFlow.DependencyInjection.Tests/SpecFlow.DependencyInjection.Tests.csproj @@ -33,6 +33,11 @@ + + True + True + ContextInjectionScope.feature + True True @@ -47,6 +52,10 @@ + + SpecFlowSingleFileGenerator + ContextInjectionScope.feature.cs + SpecFlowSingleFileGenerator diff --git a/SpecFlow.DependencyInjection.Tests/TestDependencies.cs b/SpecFlow.DependencyInjection.Tests/TestDependencies.cs index 57705dc..7f46aa3 100644 --- a/SpecFlow.DependencyInjection.Tests/TestDependencies.cs +++ b/SpecFlow.DependencyInjection.Tests/TestDependencies.cs @@ -15,6 +15,9 @@ public static IServiceCollection CreateServices() // Add test dependencies services.AddTransient(); + // ContextInjectionScope (by using AddScoped instead of AddTransient, the context will be scoped to the Feature across bindings) + services.AddScoped(); + // NOTE: This line is essential so that Microsoft.Extensions.DependencyInjection knows // about the SpecFlow bindings (something normally BoDi does automatically). // TODO: Find out if we can make this part of the Plugin