Description
If an extension exists in multiple versions within the packages folder the nunit engine does not select the highest version but always the first it finds - which is in many cases the lowest version.
Precondition:
One extension is installed in multiple versions in the packages directory, e.g.
\packages\nunit.extension.sample\1.0.0
\packages\nunit.extension.sample\2.0.0
Repro steps:
- Navigate into the folder for the nunit3-console.exe, e.g. packages\nunit.consolerunner\3.20.0\tools
- List the extensions for the runner via: nunit3-console.exe --list-extensions
Result:
- The extension with the lower version (1.0.0) is listed
Extension Point: /NUnit/Engine/TypeExtensions/IDriverFactory
Extension: SampleExtension.SampleExtension(.NET 4.0)
Version: 1.0.0.0
Path: C:.nuget\packages\nunit.extension.sample\1.0.0\net48\tools\SampleExtension.dll
Expected Result:
Extension Point: /NUnit/Engine/TypeExtensions/IDriverFactory
Extension: SampleExtension.SampleExtension(.NET 4.0)
Version: 2.0.0.0
Path: C:.nuget\packages\nunit.extension.sample\2.0.0\net48\tools\SampleExtension.dll
Affected Versions:
nunit.consolerunner.3.19.x
nunit.consolerunner.3.20.0
Workaround:
Switch to nunit.consolerunner.3.18.3 version
Root cause:
Project: nunit.engine.core
Class: Services\ExtensionManager.cs
In method ProcessCandidateAssembly the extensions are compared via IsBetterVersionOf but the new assembly is only added ByName and not updated in the _assemblies list.
line 437:
if (candidateAssembly.IsBetterVersionOf(existing))
_assemblies.ByName[assemblyName] = candidateAssembly;
line 444 - executed for the first found extension:
_assemblies.Add(candidateAssembly);
In method EnsureExtensionsAreLoaded the _assemblies is iterated but this list only contains the first extension, the latest extension is only in the 'ByName' Dictionary
line 323:
foreach (var candidate in _assemblies)
FindExtensionsInAssembly(candidate);
As local hotfix I iterated the ByName values via _assemblies.ByName.Values and after that it selected the latest version again, but I don't know if this is a valid .
foreach (var candidate in _assemblies.ByName.Values)
FindExtensionsInAssembly(candidate);
I added the two sample package folders which only contain an extension dll in different major versions which can be used to reproduce the behaviour of the --list-extensions command.
nunit.extension.sample.zip