SpecFlow icon indicating copy to clipboard operation
SpecFlow copied to clipboard

CreateInstance in SpecFlow.Assist skips row element when enum has the same value as the name of row parameter

Open privatemeta opened this issue 3 years ago • 1 comments

SpecFlow Version

3.9.74

Which test runner are you using?

SpecFlow+ Runner

Test Runner Version Number

3.9.31

.NET Implementation

equal or greater .NET Framework 4.6.1

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

{
  "language": {
    "feature": "de-AT"
  },
  "bindingCulture": {
    "name": "de-AT"
  },
  "unitTestProvider": {
    "name": "specrun"
  },
  "runtime": {
    "missingOrPendingStepsOutcome": "Error"
  },
  "stepAssemblies": [
    { "assembly": "AppServer.Shared.SpecFlow" }
  ]
}

Issue Description

Assuming you have an enum called "MyEnum" That enum has several values, one of them is "MyEnum" You use that enum in your row, you call the property "MyEnum" in the binding (or use MyEnum as its TableAlias).

if you use Specflow.Assist CreateInstance to convert this value from the string in the feature file to an enum in the step definition, the value is skipped IF and ONLY IF the enum in question is the same as the property name or table alias. Once skipped, the next value in the table is attempted to be used. If there are type differences (e.g. enum and DateTime as in the example), the type mismatch leads to an error. If more enums are used that are not named the same as your property, the parsing works correctly.

This issue appeared when upgrading from Specflow Version 3.9.8 to 3.9.74, I cannot say which version broke it exactly.

Steps to Reproduce

Use the following Binding and enum:

[Binding]
public class SampleRow
{
    public MyEnum MyEnum { get; set; }
    public DateTime MyDate { get; set; }

    [Given(@"following fields exist:")]
    public void GivenFollowingFieldsExist(SampleRow row) { }
}

[Binding]
public static class Transformations
{
    [StepArgumentTransformation]
    public static SampleRow SampleRowTransformation(Table table)
    {
        return table.CreateInstance<SampleRow>();
    }
}

public enum MyEnum
{
    MyEnum = 0,
    HisEnum = 1,
    HerEnum = 2
}

Use the following feature file:

Funktionalität: Enum-Test

Szenario: Enum-Test
Angenommen following fields exist:
	| MyEnum   | MyDate   |
	| <MyEnum> | <MyDate> |

Beispiele:
	| MyEnum  | MyDate     |
	| MyEnum  | 01.01.2020 |
	| HisEnum | 01.01.2020 |
	| HerEnum | 01.01.2020 |

Cases "HisEnum" and "HerEnuM" work. Case "MyEnum" breaks with the following error message: No enum with value '01.01.2020' found for Table row column 'MyEnum'. -> Requested value '01.01.2020' was not found.

Link to Repro Project

No response

privatemeta avatar Jul 06 '22 07:07 privatemeta

I found the issue. SpecFlow thinks the table is a horizontal table and not a vertical table. It is because the table is so small (only 1 row, 2 columns) and the first row value is the same name as a property. Code is here: https://github.com/SpecFlowOSS/SpecFlow/blob/master/TechTalk.SpecFlow/Assist/TEHelpers.cs#L222

So simply switching the order of the columns in the Scenario will fix it.

Tbh, I have no idea to fix this without breaking other people. This is so an absolute edge case.

SabotageAndi avatar Jul 12 '22 12:07 SabotageAndi