Mocking a WCF client, with a parameterised constructor for .net component called from COM

自作多情 提交于 2019-12-11 03:57:39

问题


I'm struggling to find a way forward here. I have a VB6 screen, which i need to call a .Net 'adapter' component, which calls out to a WCF service.
The WCF service is under windows authentication as i want to detect the windows logon of the user calling the functionality. The service reference is in the .Net adapter. To get this to work i have had to add detail to a binding, specifying the security, which all works fine in the real world.

My problem is unit testing this, and trying to mock the call to the WCFServiceClient. Because i am using a parametrised constructor, Moq will not mock it. So i believe that my mock is therefore not being used, and a real call is going through to the WCF layer when i run my unit test (it is, i put a break point in the wcf service running locally in my solution).

To simplify my code i've pasted a BasicHttpBinding in, as the problem isnt the security, its how do i recode the function so i can mock the call, or can i do something else allowing me to mock the call?

In the .Net adapter, in the function i am calling i have the following code

using (var myWcfService = new MyWcfServiceClient(new BasicHttpBinding (), GetEndpointAddress()))
    {
    //do stuff here
    }

In my unit test i have the following mock setup

var mockMyWcfService = new Mock<IMyWcfService>();

Which is not creating a mock that gets used by the above code. If i put parameter types into the constructor, that does not work either as Moq will only mock an interface, and a default empty constructor (i believe , from googling my previous error)

Also, although in other projects in the solution we use Unity for IOC, i do not believe i can do that in this project as the .Net adapter is called from a VB6 app, which has no app.config for me to specify all of the unity config.

Thanks


回答1:


If I understand it correctly, you have a class that uses a MyWcfServiceClient() and you want to control it's lifetime within your class (ergo the using block) therefore you cannot pass in a mocked service.

e.g.

public interface IMyWcfService {
    void DoSomething();
}

public class MyClass {
    private readonly IMyWcfService myService;

    public MyClass(IMyWcfService myService) {
        this.myService = myService;
    }

    public void DoIt() {
        myService.DoSomething();
    }
}    

What you can try is to use a provider to create the service and pass this in and use a default provider to generate the service when not unit testing.

e.g.

public interface IService : IDisposable {
}

public class DefaultService : IService {
    public void Dispose() {
    }
}

public interface IServiceProvider {
    IService GetService();
}

public class DefaultServiceProvider : IServiceProvider {
    public IService GetService() {
        return new DefaultService();
    }
}

public class Consumer {

    private readonly IServiceProvider serviceProvider;

    public Consumer() : this (new DefaultServiceProvider()){
    }

    internal Consumer(IServiceProvider serviceProvider) {
        this.serviceProvider = serviceProvider;
    }


    public void DoIt() {
        using (var service = serviceProvider.GetService()) {
          // do stuff                               
        }
    }

}

I generally make the unit test constructors internal - personal preference, not required.
In the unit test you can create a mock provider that returns a mock service.



来源:https://stackoverflow.com/questions/18344027/mocking-a-wcf-client-with-a-parameterised-constructor-for-net-component-called

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