4
votes

I am trying to Mock a generic method in a class. I am new to Moq and am not able to figure out the right way of mocking the method.

My code which needs to be tested and mocked.

public class WebServicesManager
{
    public static void Function1<TClient>()
        where TClient : SoapHttpClientProtocol, new()
    {
       //code
    }
}

The generic method Function1 accepts the generic type, which inherits from SoapHttpClientProtocol, which is basically the proxy for legacy asmx web services.

For testing the above method, am trying to mock the generic type parameter TClient. But I need the right method to do this, I tried the following code, but I am unable to find the right code.

    [TestMethod]
    public void Function1Test()
    {
        var mockService = new Mock<SoapHttpClientProtocol>();
        WebServicesManager.Function1<????>();
    }

One of the approaches that I thought of was to use a FakeClass which inherits from SoapHttpClientProtocol and then to call the generic method using the Fake class.

Also, I have read other answers here, most of them suggest to use an interface, which is correct but in my case, since the proxy code is Auto generated (client-side proxy code), so I have the limitation that I can't use the Interface.

Is it possible that I can mock the class SoapHttpClientProtocol and pass it as a generic parameter?

1
If your generic constraint requires something that can be instantiated inside of the method (new()), creating a mock instance isn't going to do anything for you.Preston Guillot
Could you elaborate more on your point? My understanding is that Moq should be able to call the constructor.Abhinav Galodha
Moq will give you an instance of a type that implements a given interface. It does not create types, hence you can't specify it as a type argument. The only way you could do this would be through getting an object from Mock and determining it's type and then creating an instance of the Function1-method through reflection, but I think you need to find a better way of doing that. If you could tell us what it is you're trying to test we could provide alternative solutions to achieve what you want to doKenneth
@Kenneth, in the WebServicesManager the Function1 is code for initialization of the web services proxy which derive from class SoapHttpClientProtocol.Abhinav Galodha
Is there any problem in just using Function1<SoapHttpClientProtocol> ? In case that's an abstract class (and thus doesn't satisfy the new()-constraint, I'd just create a fake class that inherits from it.Kenneth

1 Answers

1
votes

One of the approaches that I thought of was to use a FakeClass which inherits from SoapHttpClientProtocol and then to call the generic method using the Fake class.

Is it possible that I can mock the class SoapHttpClientProtocol and pass it as a generic parameter?

Yes, if you wrap the mock in the FakeClass.

public class FakeClient : SoapHttpClientProtocol
{
    public static Mock<SoapHttpClientProtocol> Mock { get; set; }

    public override object GetData() => Mock.Object.GetData();

    public override object SendData(object data) => Mock.Object.SendData(data);
}

[TestMethod]
public void Function1Test()
{
    FakeClient.Mock = new Mock<SoapHttpClientProtocol>();
    FakeClient.Mock.Setup(mock => mock.GetData()).Returns(...));
    FakeClient.Mock.Setup(mock => mock.SendData(It.IsAny<object>())).Callback(...));

    WebServicesManager.Function1<FakeClient>();
}