Define a method implementation in a mock object using Moq

This is the situation. I had an asynchronous call, so I needed to do an intermediate level for this to test it.

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

So, to test this without a real request, I created an interface that I can make fun of.

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

Then in the implementation, I can use a call like the one above, and I can provide some mock class to call my callback method, regardless of whether the request is valid or not. My cool class is as follows.

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

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

 var sender = new Mock<RequestSenderMock>(); 

I can not check the number of calls for this object.

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

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

 var sender = new Mock<IRequestSender>(); 

And something using an installation method or another to implement this layout. Than I just delete my cool class. Is it possible? What are you offering?

+6
source share
1 answer

I am confused that you create a manual layout and use a mocking structure to mock it (mocking the layout). I would think about porting your custom functions to some utility class and use 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 detailed settings, you can wrap the method setting in the 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>())); } 
+8
source

Source: https://habr.com/ru/post/893619/


All Articles