F # Как настроить проект FAKE, который может использовать FsUnit

Я пытаюсь настроить базовый проект FAKE F #, который может запускать FsUnit, но я не могу понять, как решить ошибки Method not found: 'Void FsUnit.TopLevelOperators.should(Microsoft.FSharp.Core.FSharpFunc`2<!!0,!!1>, !!0, System.Object)'.

Я прочитал следующие сообщения, которые кажутся связанными, но я, по-видимому, все еще не понимаю:

Я создал проект библиотеки JunkTest со следующей настройкой:

пакет.зависимости

source https://www.nuget.org/api/v2
nuget FAKE
nuget FSharp.Core
nuget FsUnit
nuget NUnit
nuget NUnit.Console

пакет.ссылки

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 (соответствующая часть)

Target "Test" (fun _ ->
    !! (buildDir + "JunkTest.dll")
    |> NUnit3 (fun p ->
        {p with OutputDir = "TestResults" }
    )
)

Вывод

Я вижу, что FSharp.Core.dll копируется из локальной директории packages: 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".

И исполнение nunit3-консоли: 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"

Я попытался добавить файл app.config с корневым каталогом тестового проекта со следующим, но это, похоже, не решает проблему (ПРИМЕЧАНИЕ. Я не использую Visual Studio - нужно ли мне делать что-то особенное, чтобы проект включал файл app.config?):

<?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>

Любая помощь приветствуется.

EDIT: Решение заключалось в том, что я неправильно настроил файл App.config для включения в сборку. Все ответы, в которых говорилось «просто добавьте это в свой файл App.config», мне не помогли, потому что VSCode не добавляет это в файл fsproj автоматически.

Часть, которую я добавил:

<None Include="App.config" />

В ItemGroup, содержащем остальные <Compile Include=Foo.fs> строк.


person Danny G    schedule 23.01.2017    source источник
comment
Включен ли файл app.config в файл fsproj?   -  person Fyodor Soikin    schedule 24.01.2017
comment
Возможный дубликат MissingMethodException при тестировании функции, которая принимает функцию параметр   -  person Mark Pattison    schedule 24.01.2017
comment
Проблема действительно была с файлом app.config, но чего я не мог найти в этом дубликате или где-либо еще, так это того, как правильно включить файл app.config в сборку. Как я уже говорил в вопросе, я не использую Visual Studio, поэтому мне помогла информация об этом, которая должна быть в fsproj.   -  person Danny G    schedule 24.01.2017


Ответы (2)


Это происходит из-за несоответствия версии FSharp.Core. Видите ли, ваше приложение ссылается на одну версию FSharp.Core, а FsUnit ссылается на другую версию. Это означает, что тип FSharpFunc<_,_> будет отличаться (из разных сборок) для вас и FsUnit, что, в свою очередь, означает, что функция should, экспортируемая FsUnit, не является той же функцией, которую ищет ваш код, потому что она имеет параметр другого типа.

Вот тут-то и появляется bindingRedirect. Вы абсолютно правильно добавили его к app.config, но из вашего вопроса о том, правильно ли вы это делаете, у меня возникает подозрение, что, возможно, нет. Дело в том, что app.config на самом деле не является конфигурацией программы. Скорее, это исходный код для настройки программы. Во время компиляции этот файл копируется в bin\Debug\Your.Project.dll.config, и только потом он будет выбран во время выполнения. Если вы не добавили этот файл в файл проекта fsproj (что, я подозреваю, может иметь место), то он не копируется в нужное место во время сборки и, следовательно, не подхватывается во время выполнения.

Другая причина, по которой он все еще не работает, может заключаться в том, что вы указали неверную версию FSharp.Core в файле app.config. Что подводит меня к следующему пункту.

Создавать этот файл вручную немного неудобно: когда вы обновляете FSharp.Core до новой версии (или Paket делает это за вас), вы можете забыть исправить это в app.config, и даже если вы этого не сделаете, это немного хлопотно. Но Paket может помочь вам в этом: если вы добавите redirects: on параметры в ваш paket.dependencies файл, Paket автоматически добавит bindingRedirect хлам в ваш app.config:

source https://www.nuget.org/api/v2
nuget FAKE
nuget FSharp.Core redirects: on
nuget FsUnit
nuget NUnit
nuget NUnit.Console
person Fyodor Soikin    schedule 23.01.2017
comment
Вы были правы, когда я неправильно настроил файл App.config в файле fsproj. Теперь это работает, хотя мне придется больше читать о перенаправлениях пакетов: on. Спасибо - person Danny G; 24.01.2017

Это похоже на несоответствие версии FSharp.Core.

Пакет NuGet, который вы используете, поставляется с FSharp.Core 4.4 (не 4.3.1). Я рекомендую изменить перенаправление привязки для использования 4.4:

<bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.4.0.0" />
person Reed Copsey    schedule 23.01.2017