F # Moq возвращает «Неверная настройка статического члена» - PullRequest
2 голосов
/ 29 мая 2019

в файле интерфейса репозитория

type public IAccountRepository =
    abstract member Find: email:string -> firstname:string -> lastname:string -> Account

в тестовом файле

open Moq
let mutable accountRepository = Mock<IAccountRepository>(MockBehavior.Strict)
accountRepository.Setup( fun rep -> rep.Find "aaa" "bbb" "ccc" ).Returns(account) |> ignore

accountRepository.Setup во время выполнения вызывает эту ошибку:

System.NotSupportedException: недопустимая настройка длястатический член: rep => FSharpFunc.InvokeFast (FuncConvert.ToFSharpFunc

Примечание. Я не хочу изменять свой метод следующим образом:
abstract member Find: email:string * firstname:string * lastname:string

Примечание 2 [добавлено]
Я не хочу использовать Object Expression , например, так:

let accountRepository_2 = {
    new IAccountRepository with
        member __.Find a b c = account   // <--- this is the only mock I need
        member __.Create x = ()
        member __.Delete x = ()
        member __.FindByMobile x = account
        member __.FindByWallet x y = account
        member __.Read x = account
    }

не является жизнеспособным решением: у меня есть 3 репозитория и 2 других провайдера для инъекций ...и я не думаю, что в этом случае все чисто.

Что это за ошибка?
Есть идеи, как издеваться над этим методом?


[Обновить]
Я обновил Moq с 4.10.1 до 4.11.0. Ошибка изменена:

System.NotSupportedException : Unsupported expression: ... => 
FSharpFunc<string, string>.InvokeFast<string, Account>(...

Я использую NSubstitute :

let accountRepository = Substitute.For<IAccountRepository>()
(accountRepository.Find "aaa" "bbb" "ccc").Returns(account) |> ignore

иэто работает.

1 Ответ

2 голосов
/ 29 мая 2019

Я бы не ожидал, что есть способ заставить это работать с Moq.Библиотека Moq предполагает, что код следует обычным методам кодирования C #, и способ, которым F # компилирует методы с несколькими параметрами в форме с карри, просто не тот способ, которым C # когда-либо определит его.

Когда вы пишете следующее в F #:

accountRepository.Setup(fun rep -> 
  rep.Find "aaa" "bbb" "ccc")

Moq на самом деле видит нечто, похожее на:

accountRepository.Setup(fun rep -> 
  rep.Find("aaa").Invoke("bbb").Invoke("ccc"))

На самом деле, это даже хуже, чем это, потому что F # выполняет оптимизацию, когда компилятор может статически определить количество параметрови сворачивает некоторые вызовы в InvokeFast call:

accountRepository.Setup(fun rep -> 
  rep.Find("aaa").InvokeFast("bbb", "ccc"))

Инструмент, который не знает об этом, не может выяснить, что это на самом деле означает вызов Find с тремя аргументами.

Я думаю, что лучшим вариантом было бы изменить сигнатуру метода (несмотря на то, что вы прямо сказали, что не хотите этого делать).В качестве альтернативы, вы можете добавить облегченную оболочку для тестирования.Еще одним вариантом было бы попробовать библиотеку F # mocking Foq и посмотреть, справится ли она с этим делом лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...