SpecFlowOSS / SpecFlow

#1 .NET BDD Framework. SpecFlow automates your testing & works with your existing code. Find Bugs before they happen. Behavior Driven Development helps developers, testers, and business representatives to get a better understanding of their collaboration
https://www.specflow.org/
Other
2.24k stars 754 forks source link

Duplicate step registrations when using AutoFac #2666

Open bjowes opened 1 year ago

bjowes commented 1 year ago

SpecFlow Version

3.9.74

Which test runner are you using?

MSTest

Test Runner Version Number

3.9.74

.NET Implementation

.NET 6.0

Project Format of the SpecFlow project

Sdk-style project format

.feature.cs files are generated using

SpecFlow.Tools.MsBuild.Generation NuGet package

Test Execution Method

Visual Studio Test Explorer

SpecFlow Section in app.config or content of specflow.json

No response

Issue Description

When using SpecFlow with the SpecFlow.AutoFac plugin, all steps are registered twice in the BindingRegistry. This causes the "Go to definition" action in the feature file view of Visual Studio to consistently fail with "Ambiguous steps". This can be worked around by selecting one of the identical "ambiguous" options, but it also causes all steps to be underlined with squiggly lines, indicating that there are multiple steps defined for them.

It is still possible to execute the tests, but the above makes maintenance and creation of tests quite tedious. Note that the steps are duplicated regardless if the GlobalDependencies or ScenarioDependencies methods are implemented, as described in the docs.

Steps to Reproduce

From Visual Studio:

Link to Repro Project

https://github.com/bjowes/specflow-duplicated-steps-repro

bjowes commented 1 year ago

Investigating the source, it seems that the root cause is this line: https://github.com/SpecFlowOSS/SpecFlow/blob/5c7dd1a0492c3b8e44f7d76ce617c2a361fa78b8/Plugins/SpecFlow.Autofac.SpecFlowPlugin/ContainerBuilderFinder.cs#L41 Is causes all steps to be registered before the GlobalDependencies container is initialized. However, all the steps are later registered again, by TestRunnerManager. Hence, all steps are present twice in the binding registry.

Suggested fix is to remove the line above. Currently, that line is required since the lookup of any methods with the GlobalDependencies attribute, performed here: https://github.com/SpecFlowOSS/SpecFlow/blob/5c7dd1a0492c3b8e44f7d76ce617c2a361fa78b8/Plugins/SpecFlow.Autofac.SpecFlowPlugin/ContainerBuilderFinder.cs#L80 relies on that bindingRegistry.GetBindingAssemlies() should return the test assembly. This can be fixed by using a different method to initialize the global container, and in that method using testAssemblyProvider.TestAssembly instead of bindingRegistry.GetBindingAssemlies(). According to the docs, the methods for GlobalDependencies and ScenarioDependencies should be placed within the SpecFlow project, so this should not break any setup that followed the docs. This way, the GlobalDependencies method is found, allowing required global container init before test execution proceeds. The steps are then only bound from TestRunnerManager.

I will gladly supply a PR for this if the suggestion makes sense.

AlbertoBN commented 1 year ago

I have the exact same problem but in only in one out of three projects using autofac.

maoso commented 7 months ago

This was opened a long time ago, any update about this bug? @gasparnagy

Thank you very much

gasparnagy commented 7 months ago

The SpecFlow project has been forked and renamed to Reqnroll. Please try if the issue is reproducible with Reqnroll using the Reqnroll VS extension and recreate the issue there if it still exists.