2

I am using C# 8.0 which supports switch expression for my project. I am recently building an unit test project and generate code coverage report. But there seems to be a problem with all switch expressions. I have some lines similar to following in my code:

private static string GenerateRequestUrl(Language language, WeatherDataType dataType) {
    var url = "https://data.weather.gov.hk/weatherAPI/opendata/weather.php?";

    url += language switch {
        Language.English => "lang=en",
        Language.TraditionalChinese => "lang=tc",
        Language.SimplifiedChinese => "lang=sc",
        _ => "lang=en"
    };

    url += dataType switch {
        WeatherDataType.LocalWeatherForecast => "&dataType=flw",
        WeatherDataType.NineDaysWeather => "&dataType=fnd"
    };

    return url;
}

And my test method covers all situations above, but the report shows those lines with switch expressions are not covered. Like in this image: Coverage Highlights in JetBrains Rider

What should I do to make them covered.

shingzh
  • 121
  • 1
  • 7
  • 1
    Upgrade your test framework and tooling. I would guess it does not support those features. – fredrik Aug 29 '20 at 13:51
  • What version of Rider are you using? – devNull Aug 29 '20 at 14:31
  • I am using the latest version of Rider 2020.2.1 – shingzh Aug 29 '20 at 14:37
  • Are tests passing if you're using old-style switch? If yes, is this a .NET Framework project? If yes, have you installed required Nuget package? https://stackoverflow.com/questions/56651472/does-c-sharp-8-support-the-net-framework/57020770#57020770 – Roar S. Aug 29 '20 at 15:51
  • please provide a minimal working solution or a github link to your project. – hce Aug 31 '20 at 13:30

1 Answers1

4

Although it may not be the answer you hoped for, it seems that the code coverage doesn't work with non-sequential switch expressions.

When you look at the IL Code, the new C# 8.0 switch expression is first calculating (jumping) which expression is true and then setting the url.
Whereas the sequential switch statement sets the url after the case statement.

So if you want a full coverage you should use the sequential switch statement (like for the WeatherDataType in the code below).

Code

enter image description here

IL Code

    .method public hidebysig static string  GenerateRequestUrl(valuetype Demo.Generator/Language language,
                                                           valuetype Demo.Generator/WeatherDataType dataType) cil managed
{
  // Code size       130 (0x82)
  .maxstack  2
  .locals init (string V_0,
           string V_1,
           string V_2,
           valuetype Demo.Generator/WeatherDataType V_3,
           valuetype Demo.Generator/WeatherDataType V_4,
           string V_5)
  IL_0000:  nop
  IL_0001:  ldstr      "https://data.weather.gov.hk/weatherAPI/opendata/we"
  + "ather.php\?"
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  stloc.1
  IL_0009:  ldc.i4.1
  IL_000a:  brtrue.s   IL_000d
  IL_000c:  nop
  IL_000d:  ldarg.0
  IL_000e:  switch     ( 
                        IL_0021,
                        IL_0029,
                        IL_0031)
  IL_001f:  br.s       IL_0039
  IL_0021:  ldstr      "lang=en"
  IL_0026:  stloc.2
  IL_0027:  br.s       IL_0041
  IL_0029:  ldstr      "lang=tc"
  IL_002e:  stloc.2
  IL_002f:  br.s       IL_0041
  IL_0031:  ldstr      "lang=sc"
  IL_0036:  stloc.2
  IL_0037:  br.s       IL_0041
  IL_0039:  ldstr      "lang=en"
  IL_003e:  stloc.2
  IL_003f:  br.s       IL_0041
  IL_0041:  ldc.i4.1
  IL_0042:  brtrue.s   IL_0045
  IL_0044:  nop
  IL_0045:  ldloc.1
  IL_0046:  ldloc.2
  IL_0047:  call       string [System.Runtime]System.String::Concat(string,
                                                                    string)
  IL_004c:  stloc.0
  IL_004d:  ldarg.1
  IL_004e:  stloc.s    V_4
  IL_0050:  ldloc.s    V_4
  IL_0052:  stloc.3
  IL_0053:  ldloc.3
  IL_0054:  brfalse.s  IL_005e
  IL_0056:  br.s       IL_0058
  IL_0058:  ldloc.3
  IL_0059:  ldc.i4.1
  IL_005a:  beq.s      IL_006c
  IL_005c:  br.s       IL_007a
  IL_005e:  ldloc.0
  IL_005f:  ldstr      "&dataType=flw"
  IL_0064:  call       string [System.Runtime]System.String::Concat(string,
                                                                    string)
  IL_0069:  stloc.0
  IL_006a:  br.s       IL_007a
  IL_006c:  ldloc.0
  IL_006d:  ldstr      "&dataType=fnd"
  IL_0072:  call       string [System.Runtime]System.String::Concat(string,
                                                                    string)
  IL_0077:  stloc.0
  IL_0078:  br.s       IL_007a
  IL_007a:  ldloc.0
  IL_007b:  stloc.s    V_5
  IL_007d:  br.s       IL_007f
  IL_007f:  ldloc.s    V_5
  IL_0081:  ret
} // end of method Generator::GenerateRequestUrl
hce
  • 1,107
  • 9
  • 25