Подтвердить что ты не робот

Как вызвать конструктор с аргументами интерфейса при издевательском конкретном классе с 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, но не если он принимает интерфейсы, которые я издеваюсь. Как вы это делаете?

4b9b3361

Ответ 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.: Я начал щедрость по ошибке (у меня была неправильная подпись в моем конструкторе).