Как вызывать конструктор с аргументами интерфейса при макете конкретного класса с помощью Moq
У меня есть следующий класс, который использует конструктор инъекций:
public class Service : IService
{
public Service(IRepository repository, IProvider provider) { ... }
}
Для большинства методов этого класса я просто создаю Moq mocks для IRepository
а также IProvider
и построить Service
, Однако в классе есть один метод, который вызывает несколько других методов в том же классе. Для тестирования этого метода, вместо того, чтобы тестировать все эти методы вместе, я хочу проверить, что метод вызывает эти методы правильно и обрабатывает их возвращаемые значения правильно.
Лучший способ сделать это - издеваться Service
, Я без проблем издевался над конкретными классами с Moq. Я даже издевался над конкретными классами, которые требуют аргументов конструктора с Moq без проблем. Тем не менее, это первый раз, когда мне нужно было передать ложные аргументы в конструктор для ложного объекта. Естественно, я попытался сделать это так:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
Однако это не работает. Вместо этого я получаю следующую ошибку:
Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: My.Namespace.Service.
Could not find a constructor that would match given arguments:
Castle.Proxies.IRepository
Castle.Proxies.IProvider
Это работает нормально, если Service
конструктор принимает простые аргументы, такие как int
с и string
с, но не, если он принимает интерфейсы, которые я издеваюсь. Как ты это делаешь?
3 ответа
Почему вы издеваетесь над сервисом, который тестируете? Если вы хотите протестировать реализацию класса Service (будь то вызовы для ложных объектов или нет), все, что вам нужно, это макеты для двух интерфейсов, а не тестовый класс.
Вместо:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
Не должно ли это быть вместо этого?
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Service(repository.Object, provider.Object);
Я понимаю, что в некоторых рамках можно смоделировать конкретные объекты, но какова ваша цель? Идея насмешек над чем-то состоит в том, чтобы удалить реальную реализацию, чтобы она не влияла на ваш тест. Но в своем вопросе вы заявили, что хотите знать, что определенные классы вызываются должным образом, и затем вы хотите проверить результаты этих действий. Это, несомненно, тестирование реализации, и по этой причине мне трудно увидеть цели насмешки над конкретным объектом.
У меня была очень похожая проблема, когда мой эквивалент Service
имел внутренний конструктор, поэтому он не был виден Moq.
я добавил
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
в мой файл AssemblyInfo.cs для реализации проекта. Не уверен, что это уместно, но я хотел добавить предложение о том, что он поможет вам или кому-то еще.
Это должно быть проблема старой версии, все в порядке с последней версией. Ник, пожалуйста, проверьте!
Ps: я начал щедрость по ошибке (у меня была неправильная подпись в моем конструкторе).