简体   繁体   English

如何使用 moq 模拟嵌套服务调用

[英]How do I mock nested service call using moq

I have a statement similar to我有一个类似的声明

var res = _serviceA.MethodA(() => _serviceB.MethodB(new objectA(){ Id = 10 }) 

which is being called twice in the method and also the response changes based on the value of Id , hence I need to setup the response such that a different object is returned based on the the Id value.它在方法中被调用两次,并且响应也会根据Id的值发生变化,因此我需要设置响应,以便根据Id值返回不同的对象。

Current mock:当前模拟:

_serviceAMock.Setup(x => x.MethodA(It.IsAny<Func<ResponseObject>>())).Return(responseOfTypeResponseObject);

Is it possible to achieve this using moq?是否可以使用最小起订量来实现这一目标? if yes how?如果是的话怎么办? I was able to mock MethodA and get the response but I couldn't figure out how to mock it such that the result varies based on the Id value.我能够模拟MethodA并获得响应,但我无法弄清楚如何模拟它以使结果根据Id值而变化。

Mocking Class:模拟类:

public class ClassToTest
    {
        private readonly IServiceA<int> _serviceA;
        private readonly IServiceB _serviceB;

        public ClassToTest(IServiceA<int> serviceA, IServiceB serviceB)
        {
            _serviceA = serviceA;
            _serviceB = serviceB;
        }

        public void MethodToTest()
        {
            var res = _serviceA.MethodA(() => _serviceB.MethodB(new ObjectA() { Id = 10 }));
        }

    }

Supporting objects:支持对象:

public class ObjectA
{
    public int Id { get; set; }
}

public interface IServiceB
{
    int MethodB(ObjectA objectA);
}

public interface IServiceA<T>
{
    T MethodA(Func<T> handler);
}

That worked for me:这对我有用:

using FluentAssertions;
using Moq;

namespace MockDifferentResult;

public class Tests
{
    [Test]
    public void Test1()
    {
        // Arrange
        var serviceBMock = new Mock<IServiceB>();
        serviceBMock
            .Setup(service => service.MethodB(It.Is<ObjectA>(a => a.Id == 10)))
            .Returns(1);
        serviceBMock
            .Setup(service => service.MethodB(It.Is<ObjectA>(a => a.Id == 20)))
            .Returns(2);
        var serviceAMock = new Mock<IServiceA<int>>();
        serviceAMock
            .Setup(service => service.MethodA(It.IsAny<Func<int>>()))
            .Returns<Func<int>>(handler => handler());
        var testee = new ClassToTest(serviceAMock.Object, serviceBMock.Object);
        
        // Act
        testee.MethodToTest();
        
        // Assert
        testee.Res1.Should().Be(1);
        testee.Res2.Should().Be(2);
    }
}

public class ClassToTest
{
    private readonly IServiceA<int> _serviceA;
    private readonly IServiceB _serviceB;
    
    public int Res1 { get; private set; }
    public int Res2 { get; private set; }

    public ClassToTest(IServiceA<int> serviceA, IServiceB serviceB)
    {
        _serviceA = serviceA;
        _serviceB = serviceB;
    }

    public void MethodToTest()
    {
        Res1 = _serviceA.MethodA(() => _serviceB.MethodB(new ObjectA { Id = 10 }));
        Res2 = _serviceA.MethodA(() => _serviceB.MethodB(new ObjectA { Id = 20 }));
    }
}

public class ObjectA
{
    public int Id { get; set; }
}

public interface IServiceB
{
    int MethodB(ObjectA objectA);
}

public interface IServiceA<T>
{
    T MethodA(Func<T> handler);
}

Please give it a try and see if it suffices your needs.请试一试,看看它是否满足您的需求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM