When the nuget package contains a native dll in /runtimes/{RID}/native/foo.dll and the top level application or unit test project is built with that RID either by specifying in the csproj <RuntimeIdentifier>{RID}</RuntimeIdentifier> or on the command line with dotnet build -r {RID} (I think msbuild /p:RuntimeIdentifier={RID} also works) the native dll is placed in the output directory. From that point, the .net dll from the nuget package can contain P/Invoke with [DllImport("foo")] in order to import the exported native function, and consumers of the nuget package can just use the nuget package like a normal .net package, as long as they set the RID on the application or unit test project.
If building without the RID, the .net wrapper library that contains the P/Invoke will be deployed to the output directory, but the native library will not, in which case it will throw an exception: System.DllNotFoundException: Unable to load DLL 'foo'
You can also specify multiple RIDs in the csproj e.g. <RuntimeIdentifiers>win-x86;win-x64;linux-x64</RuntimeIdentifiers> and then dotnet build (or dotnet publish -r {RID}) will produce an output directory for each RID, each with the appropriate assemblies, in a similar way to <TargetFrameworks>
It may just be because NCrunch is using msbuild (I assume) rather than dotnet build, and dotnet build is probably doing something on top of what msbuild does. Passing the RuntimeIdentifier/RuntimeIdentifiers properties from the csproj to msbuild /p: may fix it, or switching to dotnet build, perhaps by an option in the NCrunch project config.