Как вызвать конструктор с аргументами интерфейса при издевательском конкретном классе с Moq
У меня есть следующий класс, который использует инъекцию конструктора:
public class Service : IService
{
public Service(IRepository repository, IProvider provider) { ... }
}
Для большинства методов этого класса я просто создаю Moq mocks для IRepository
и IProvider
и создаю Service
. Однако в классе есть один метод, который вызывает несколько других методов в одном классе. Для тестирования этого метода вместо того, чтобы тестировать все эти методы вместе, я хочу проверить, правильно ли метод правильно эти методы и правильно ли обрабатывает возвращаемые значения.
Лучший способ сделать это - издеваться над Service
. Я издевался над конкретными классами с Moq, прежде чем без проблем. Я даже издевался над конкретными классами, которые без аргументов требуют аргументов конструктора с Moq. Тем не менее, это первый раз, когда мне нужно передать аргументы mocked в конструктор для издевающегося объекта. Естественно, я пытался сделать это следующим образом:
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
s, но не если он принимает интерфейсы, которые я издеваюсь. Как вы это делаете?
Ответы
Ответ 1
У меня была очень похожая проблема, когда у моего эквивалента Service
был внутренний конструктор, поэтому он не был виден Moq.
Я добавил
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
в файл AssemblyInfo.cs для проекта реализации. Не уверен, что это актуально, но я хотел добавить предложение о том, что он помогает вам или кому-то еще.
Ответ 2
Почему вы издеваетесь над тестируемым сервисом? Если вы хотите протестировать реализацию класса Service (будь то вызовы обманутых объектов или нет), все, что вам нужно, это mocks для двух интерфейсов, а не для тестового класса.
Вместо:
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);
Я понимаю, что в некоторых рамках можно издеваться над конкретными объектами, но какова ваша цель? Идея насмешки над чем-то заключается в том, чтобы удалить фактическую реализацию, чтобы она не влияла на ваш тест. Но в вашем вопросе вы заявили, что хотите знать, что определенные классы вызываются должным образом, а затем вы хотите проверить результаты этих действий. Это, несомненно, проверяет реализацию, и по этой причине мне с трудом удается понять цели издевательств над конкретным объектом.
Ответ 3
Должна быть проблема с старой версией, все в порядке с последней версией. Ник, пожалуйста, проверьте!
P.s.: Я начал щедрость по ошибке (у меня была неправильная подпись в моем конструкторе).