Moq и доступ к названным параметрам

Я только что начал реализовывать модульные тесты (использующий xUnit и Moq) на уже установленном моем проекте. Проект экстенсивно использует внедрение зависимости через контейнер единицы.

У меня есть два сервиса A и B. Сервис A является тем, протестированным в этом случае. Обслужите вызовы B, и дает ему делегата во внутренней функции. Этот 'обратный вызов' используется для уведомления, когда сообщение было получено, что это должно обработать.

Следовательно вызовы (где b является экземпляром сервиса B):

b.RegisterHandler(Guid id, Action<byte[]> messageHandler);

Для тестирования сервиса A я должен смочь звонить messageHandler, поскольку это - единственный способ, которым это в настоящее время принимает сообщения.

Это может быть сделано с помощью Moq? т.е. я могу дразнить сервис B, такой что когда RegisterHandler назван, значение messageHandler роздан к моему тесту?

Или я должен перепроектировать это? Есть ли какие-либо шаблоны разработки, которые я должен использовать в этом случае? Кто-либо знает о каких-либо хороших ресурсах на этом виде дизайна?

5
задан Ruben Bartelink 13 April 2010 в 08:11
поделиться

2 ответа

Можно получить экземпляр обратного вызова (или любой другой входной параметр) при помощи Обратного вызова (, подобие имени несущественно ), метод на Насмешке:

[TestMethod]
public void Test19()
{
    Action<byte[]> callback = null;

    var bSpy = new Mock<IServiceB>();
    bSpy.Setup(b => b.RegisterHandler(It.IsAny<Guid>(), It.IsAny<Action<byte[]>>()))
        .Callback((Guid g, Action<byte[]> a) => callback = a);

    var sut = new ServiceA(bSpy.Object);
    sut.RegisterCallback();

    Assert.AreEqual(sut.Do, callback);
}

Это работает, когда ServiceA определяется как это:

public class ServiceA
{
    private readonly IServiceB b;

    public ServiceA(IServiceB b)
    {
        if (b == null)
        {
            throw new ArgumentNullException("b");
        }

        this.b = b;
    }

    public void RegisterCallback()
    {
        this.b.RegisterHandler(Guid.NewGuid(), this.Do);
    }

    public void Do(byte[] bytes)
    {
    }
}
9
ответ дан 14 December 2019 в 01:08
поделиться

Да можно установить объект Moq ответить на ожидаемые и неожиданные операции. Вот пример Модульного теста Visual Studio...

[TestMethod]
public void MyTest()
    {
      var moqObject = new Mock<ServiceB>();

      // Setup the mock object to throw an exception if a certain value is passed to it...
      moqObject.Setup(b => b.RegisterHandle(unexpectedValue).Throws(new ArgumentException());

      // Or, setup the mock object to expect a certain method call...
      moqObject.Setup(b => b.RegisterHandle(expectedValue));

      var serviceA = new ServiceA(moqObject.Object);

      serviceA.DoSomethingToTest();

      // This will throw an exception if an expected operation didn't happen...
      moqObject.VerifyAll();
    }
0
ответ дан 14 December 2019 в 01:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: