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.25k stars 754 forks source link

Cannot define more than one method with the AssemblyInitialize attribute inside an assembly #1792

Closed p2kdev closed 4 years ago

p2kdev commented 4 years ago

Error while running test after updating Specflow to 3.1.67 & .NETCore 3.0 due to AssemblyInitialize attribute hook error

SpecFlow Version:

Used Test Runner

Version number: 2.0.0

Project Format of the SpecFlow project

.feature.cs files are generated using

Visual Studio Version

Enable SpecFlowSingleFileGenerator Custom Tool option in Visual Studio extension settings

Are the latest Visual Studio updates installed?

.NET Framework:

Test Execution Method:

Issue Description

I changed the framework on my project this morning to .NET Core 3.0 & started receiving error **Message:

    Class Initialization method EN.PCc.StxTests.Features.DataExport.ProductExportFeature.FeatureSetup threw exception. System.ArgumentNullException: System.ArgumentNullException: Value cannot be null. (Parameter 'key').
  Stack Trace: 
    Dictionary`2.FindEntry(TKey key)
    Dictionary`2.TryGetValue(TKey key, TValue& value)
    RuntimeBindingRegistryBuilder.FindAttributeConstructorArg(ParameterInfo parameterInfo, Dictionary`2 namedAttributeValues)
    <>c__DisplayClass8_0.<CreateAttribute>b__7(ParameterInfo p)
    SelectArrayIterator`2.ToArray()
    RuntimeBindingRegistryBuilder.CreateAttribute(Attribute attribute)
    WhereSelectEnumerableIterator`2.ToArray()
    RuntimeBindingRegistryBuilder.GetAttributes(IEnumerable`1 customAttributes)
    RuntimeBindingRegistryBuilder.CreateBindingSourceMethod(MethodInfo methodDefinition)
    RuntimeBindingRegistryBuilder.BuildBindingsFromType(Type type)
    RuntimeBindingRegistryBuilder.BuildBindingsFromAssembly(Assembly assembly)
    TestRunnerManager.BuildBindingRegistry(IEnumerable`1 bindingAssemblies)
    TestRunnerManager.InitializeBindingRegistry(ITestRunner testRunner)
    TestRunnerManager.CreateTestRunner(Int32 threadId)
    TestRunnerManager.GetTestRunnerWithoutExceptionHandling(Int32 threadId)
    TestRunnerManager.GetTestRunner(Int32 threadId)
    TestRunnerManager.GetTestRunner(Assembly testAssembly, Nullable`1 managedThreadId)
    ProductExportFeature.FeatureSetup(TestContext testContext)

I checked the nuget package section & there were updates for specflow, Specflow.Tools.MsBuild.Generation, Specflow.MSTest from 3.0.225 to 3.1.67. I upgraded the packages & when I try running my test, I am getting the error
UTA013 : Cannot define more than one method with the AssemblyInitialize attribute inside an assembly

In my project there is an AssemblyInitialize method which does the test environment initialization & is required. If I remove the attribute on the method, then everything works, but as I said this is required for our project

SabotageAndi commented 4 years ago

This is a duplicate of https://github.com/techtalk/SpecFlow/issues/1787

Reason of this error:

Because of #1348 we had to change how the BeforeTestRun/AfterTestRun hooks are executed. We are now using the unit test provided integration. That's were the double definition of the [AssemblyInitialize] attribute comes from.

Please use the hooks SpecFlow is providing you and not the attributes from your unit test provider. In this case the [BeforeTestRun] hook.

david1995 commented 4 years ago

Hi @p2kdev, since SpecFlow 3.1 we inject our own AssemblyInitialize and AssemblyCleanup methods into SpecFlow test projects to call the BeforeTestRun and AfterTestRun hooks. Please do not use unit test provider specific Assembly initialization or cleanup code from SpecFlow 3.1 on. Instead, use the BeforeTestRun and AfterTestRun hooks provided by SpecFlow. See the documentation here: https://specflow.org/documentation/Hooks/

SabotageAndi commented 4 years ago

Closed because of inactivity

fder77 commented 4 years ago

I understand that it is not recommended to use a specific Assembly initialization but my test assembly has external dependencies (like SDK dlls) so I need to setup an Assembly resolving before calling TestRunnerManager.OnTestRunStart(currentAssembly) otherwise there is a System.IO.FileNotFoundException on it;

Like this :

[AssemblyInitialize]
        public static void AssemblyInit(TestContext context)
        {
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve;
            var currentAssembly = typeof(TestAssembly).Assembly;
            TestRunnerManager.OnTestRunStart(currentAssembly);
        }

        private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
        {
            ....

        }

So in my case, I 'm still using my own AssemblyInitialize method. I cannot move it to [BeforeTestRun] hook method.

mrtaunus commented 4 years ago

In our case we use the [AssemblyInitialize] method to inject the MSTest TestContext, from where we read a test run setting and based on that, we generate or skip a local database with test data. This setting comes from Azure Devops pipeline, and thus the TestContext is the only way we have found to provide it. We are also stuck on a pre 3.1 Specflow version because of this.

public static bool DeployIntegrationDatabase { get; set; }

[AssemblyInitialize]
public static void AssemblyInit( TestContext context )
{
    DeployIntegrationDatabase = bool.Parse( context.Properties["DeployIntegrationDatabase"].ToString() );
}

[BeforeTestRun]
public static void BeforeTestRun()
{
    if ( DeployIntegrationDatabase )
    { IntegrationTestDatabaseDeployer.DeployTestSqlDatabase(); }
}
SabotageAndi commented 4 years ago

@mrtaunus Oh, that's bad. We weren't aware that the TestContext is accessible in the AssemblyInitialize. For the normal scenarios, you can you can request the TestContext via Context Injection from SpecFlow.

See https://github.com/SpecFlowOSS/SpecFlow/blob/master/Tests/TechTalk.SpecFlow.Specs/Features/UnitTestProviderSpecific/MsTest/TestContext.feature

I created an issue for this: https://github.com/SpecFlowOSS/SpecFlow/issues/1859

github-actions[bot] commented 3 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.