Define method implementation in mock object using Moq

假装没事ソ 提交于 2019-12-23 09:46:34

问题


This is the situation. I had async call so I needed to make Mid tier for this in order to be able to test it.

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

So, in order to be able to test this without real request, I created interface which I can mock.

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

Then in implementation I can use call like that one above and I can provide some mock class to call my callback method regardless request is valid or not. My mock class looks like this.

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);
        }
    }

I can now easily create mock object in my unit test and use it. But when I create

var sender = new Mock<RequestSenderMock>();

I'm unable to verify call count for this object.

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

It says that my method needs to be virtual. Is there a way to do this without making my method virtual? It would be best if I could somehow specify method impelementation when using interface.

var sender = new Mock<IRequestSender>();

And that somehow with Setup method or some other to make implementation on this mock object. Than I'll simply remove my mock class. Is this possible? What do you suggest?


回答1:


I find it confusing that you are creating a manual mock and using a mocking-framework to mock it (mocking a mock). I would consider moving your custom functions into some utility class and using callbacks instead.

Example:

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>()));
    }

To avoid the verbose setup you can wrap the setup of the method in an extension method and change your test accordingly:

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>()));
    }


来源:https://stackoverflow.com/questions/6834126/define-method-implementation-in-mock-object-using-moq

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!