开发者

Define method implementation in mock object using Moq

开发者 https://www.devze.com 2023-03-22 21:04 出处:网络
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.

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 M开发者_JAVA技巧ock<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?


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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号