问题
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