I'm trying to setup a basic FAKE F# project that can run FsUnit but I cannot figure out how to solve the Method not found: 'Void FsUnit.TopLevelOperators.should(Microsoft.FSharp.Core.FSharpFunc`2<!!0,!!1>, !!0, System.Object)' errors.
I have read the following posts that seem to be related, but I'm apparently still not grokking it:
- Main github issue
- FSharp.Core packaging guidelines
- FsUnit unable to test portable library (SO)
- Another github issue
I have created a JunkTest library project with the following setup:
paket.dependencies
source https://www.nuget.org/api/v2
nuget FAKE
nuget FSharp.Core
nuget FsUnit
nuget NUnit
nuget NUnit.Console
paket.references
FSharp.Core
FsUnit
NUnit
JunkTest.fs
module JunkTest
open FsUnit
open NUnit.Framework
[<Test>]
let ``Example Test`` () =
1 |> should equal 1 // this does not work
//Assert.That(1, Is.EqualTo(1)) // this works (NUnit)
build.fsx (relevant part)
Target "Test" (fun _ ->
!! (buildDir + "JunkTest.dll")
|> NUnit3 (fun p ->
{p with OutputDir = "TestResults" }
)
)
Output
I see that FSharp.Core.dll is being copied from the local packages directory: Copying file from "c:\Users\dangets\code\exercism\fsharp\dgt\packages\FSharp.Core\lib\net40\FSharp.Core.dll" to "c:\Users\dangets\code\exercism\fsharp\dgt\build\FSharp.Core.dll".
And the nunit3-console execution: c:\Users\dangets\code\exercism\fsharp\dgt\packages\NUnit.ConsoleRunner\tools\nunit3-console.exe "--noheader" "--output=TestResults" "c:\Users\dangets\code\exercism\fsharp\dgt\build\JunkTest.dll"
I have tried to add a app.config file with the in the test project root directory with the following but it doesn't seem to solve the issue (NOTE I am not using Visual Studio - do I need to do anything special for the project to include the app.config file?):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.3.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Any and all help is appreciated.
EDIT: The solution was that I was not properly setting up the App.config file to get included in the build. All of the answers that said "just add this to your App.config file" didn't help me because VSCode doesn't add this to the fsproj file automatically.
The part that I added is:
<None Include="App.config" />
In the ItemGroup that contains the other <Compile Include=Foo.fs> lines.
This happens because of
FSharp.Coreversion mismatch. See, your application references one version ofFSharp.CoreandFsUnitreferences another version. This means that theFSharpFunc<_,_>type is going to be different (coming from different assemblies) for you andFsUnit, which in turn means that theshouldfunction exported byFsUnitis not the same function that your code is looking for, because it has a parameter of a different type.This is where the
bindingRedirectcomes in. You're absolutely correctly added it toapp.config, but from your question about whether you're doing it correctly, I get a suspicion that you might not. The thing withapp.configis, it's not actually the program configuration. Rather, it's the source code for program configuration. At compile time, this file gets copied tobin\Debug\Your.Project.dll.config, and only then it will get picked up at runtime. If you didn't add this file to thefsprojproject file (which, I suspect, might be the case), then it's not getting copied to the right place during build, and thus isn't getting picked up at runtime.Another reason for it still not working may be that you've specified an incorrect version of
FSharp.Corein yourapp.configfile. Which brings me to the next point.Crafting that file by hand is a bit fragile: when you upgrade
FSharp.Coreto a new version (or Paket does it for you), you may forget to fix it inapp.configand even if you don't, it's a bit of a hassle. But Paket can help you with that: if you add theredirects: onoptions to yourpaket.dependenciesfile, Paket will add thebindingRedirectcruft to yourapp.configautomatically: