В качестве дополнительного примечания вы можете использовать неявный синтаксис конструктора, чтобы сделать объявление класса немного более приятным. Вы также можете упростить свойства только для чтения, потому что можете опустить with get()
:
// F# infers that the type is an interface
type ICustomer =
abstract Id : int
abstract Name : string
abstract CalculateBalanceWithDiscount : decimal -> decimal
// Parameters of the implicit constructor are autoamtically
// accessible in the body (they are stored as fields)
type Customer(id:int, name:string, balance:decimal) =
interface ICustomer with
member this.Id = id
member this.Name = name
member this.CalculateBalanceWithDiscount(discount) =
balance - (discount * balance)
Что касается тестирования - есть ли у вас пример того, чего вы пытаетесь достичь? Я уверен, что мы можем помочь, например, с переводом кода из C #. Или какие тесты вы хотели бы написать с помощью насмешек?
В целом, хорошая вещь в F # и функциональных языках заключается в том, что вы обычно можете тестировать код легче, не используя при этом какие-либо насмешки. Функциональные программы написаны в другом стиле:
В функциональном программировании функция принимает все свои входные данные в качестве аргументов, и единственное, что она делает, - это то, что она вычисляет и возвращает некоторый результат. Это также верно для методов неизменяемых типов объектов - они не изменяют состояние каких-либо объектов
Моки обычно используются для двух целей:
Чтобы убедиться, что тестируемая операция выполнила некоторый вызов метода ссылочного объекта, например, prod.Update(newPrice)
чтобы обновить состояние объекта. Однако в функциональном программировании метод должен вместо этого возвращать новое состояние в качестве результата, поэтому вам не нужен фиктивный объект. Просто проверьте, является ли новое возвращенное состояние ожидаемым.
Для загрузки создайте поддельный компонент приложения, например, вместо загрузки данных из базы данных. Опять же, чисто функциональная функция должна принимать все свои входные данные в качестве аргументов. Это означает, что вам не нужно создавать фиктивный объект - вы просто вызываете функцию с некоторыми тестовыми данными в качестве аргумента (вместо данных, загруженных из базы данных).
Таким образом, это означает, что в хорошо разработанной функциональной программе вы должны иметь возможность писать все модульные тесты просто как проверки, которые проверяют, что какая-то функция возвращает ожидаемый результат для ожидаемых аргументов. Конечно, это не совсем верно в F #, потому что вам может потребоваться взаимодействие с другими нечистыми компонентами .NET (но на это можно ответить, только если вы приведете более конкретный пример).