【问题标题】:Define method implementation in mock object using Moq使用 Moq 在模拟对象中定义方法实现
【发布时间】:2011-07-26 17:36:30
【问题描述】:

情况就是这样。我有异步调用,所以我需要为此设置中间层以便能够对其进行测试。

request.BeginGetResponse(new AsyncCallback(LoginCallback), requestState);

所以,为了能够在没有真正请求的情况下进行测试,我创建了可以模拟的接口。

public interface IRequestSender
    {
        void Send(HttpWebRequest request, AsyncCallback internalCallback, object requestState);
    }

然后在实现中我可以使用上述调用,并且我可以提供一些模拟类来调用我的回调方法,无论请求是否有效。我的模拟类是这样的。

public class RequestSenderMock : IRequestSender
    {
        public void Send(HttpWebRequest request, AsyncCallback internalCallback, object requestState)
        {
            var result = new Mock<IAsyncResult>();
            result.Setup(x => x.AsyncState).Returns(requestState);
            internalCallback(result.Object);
        }
    }

我现在可以轻松地在我的单元测试中创建模拟对象并使用它。但是当我创建时

var sender = new Mock<RequestSenderMock>();

我无法验证此对象的调用次数。

sender.Verify(x => x.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>()), Times.Once());

它说我的方法需要是虚拟的。 有没有办法在不使我的方法虚拟化的情况下做到这一点?如果我能在使用接口时以某种方式指定方法实现,那将是最好的。

var sender = new Mock<IRequestSender>();

并且以某种方式使用 Setup 方法或其他方法在此模拟对象上实现。比我简单地删除我的模拟课程。 这可能吗?你有什么建议?

【问题讨论】:

    标签: c# mocking moq


    【解决方案1】:

    您正在创建手动模拟并使用模拟框架来模拟它(模拟模拟),这让我感到困惑。我会考虑将您的自定义函数移动到某个实用程序类中,并改用回调。

    例子:

    public class RequestSenderHelpers
    {
        public static void Send(HttpWebRequest request, AsyncCallback internalCallback, object requestState)
        {
            var result = new Mock<IAsyncResult>();
            result.Setup(x => x.AsyncState).Returns(requestState);
            internalCallback(result.Object);
        }
    
    }
    
        [Test]
        public void Callback_VerifyingWithMethodImplementation_VerifyWorks()
        {
            // arrange
            var sender = new Mock<IRequestSender>();
            sender.Setup(s => s.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>())).Callback<HttpWebRequest, AsyncCallback, object>(RequestSenderHelpers.Send);
    
            // act
            sender.Object.Send(null, delegate {}, null);
    
            // assert
            sender.Verify(s => s.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>()));
        }
    

    为了避免冗长的设置,您可以将方法的设置包装在扩展方法中并相应地更改您的测试:

    public static class RequestSenderHelpers
    {
        public static void Send(HttpWebRequest request, AsyncCallback internalCallback, object requestState)
        {
            var result = new Mock<IAsyncResult>();
            result.Setup(x => x.AsyncState).Returns(requestState);
            internalCallback(result.Object);
        }
    
        public static void SetupSendWithMockedAsyncResult(this Mock<IRequestSender> sender)
        {
            sender.Setup(s => s.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>())).Callback<HttpWebRequest, AsyncCallback, object>(Send);            
        }
    
    }
    
        [Test]
        public void Callback_VerifyingWithMethodImplementation_VerifyWorks()
        {
            // arrange
            var sender = new Mock<IRequestSender>();
            sender.SetupSendWithMockedAsyncResult();
    
            // act
            sender.Object.Send(null, delegate {}, null);
    
            // assert
            sender.Verify(s => s.Send(It.IsAny<HttpWebRequest>(), It.IsAny<AsyncCallback>(), It.IsAny<object>()));
        }
    

    【讨论】:

    • 谢谢,这正是我所需要的。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    • 2010-11-12
    • 2023-03-12
    • 2011-10-26
    相关资源
    最近更新 更多