Reputation: 2832
I want to fake the getCustomerName Service call here and mock it with fake Data
My class is "CustomerName" which calls a SOAPService call which returns the CustomerName for an CustomerNumber.I want to fake the SOAPService call to return some fakedata.
CustomerName class:
using (WebService.WebServiceClient CustomerData = new WebService.WebServiceClient ())
{
WebServiceClient.TestResponse resp = CustomerData.getCustomerName(customerNumber);
resp.CustomerName;
}
I tried doing these
var FakeWebService = A.Fake<WebServiceClient>();
var FakeCustomerName=A.Fake<CustomerName>();
Then I faked the Calls here and Fake response is some value
A.CallTo(WebServiceClient.CustomerNumber).WithNonVoidReturnType().Returns(FakeResponse);
fakeCustomerName = FakeCustomerData.GetCustomerName(CustomerNumber);
The problem I face is it's getting the data from the actual endpoint instead of fakedata?
I am not clear on how to do it..
Upvotes: 4
Views: 4403
Reputation: 241980
There are several problems with your approach. For starters, you can only fake virtual methods (or abstract ones, or methods defined on interfaces). I assume that WebService.WebServiceClient.getCustomerName
is not virtual, so here's an alternative to @Micael's answer that will get you around that. I've used it many times in the past:
Like Micael says, create an interface instead which holds the functionality the webservice provides.
public interface ICustomerData
{
CustomerName GetCustomerName(CustomerNumber number);
}
Then you can make your production collaborator CustomerData
as he did, or if WebService.WebServiceClient
is not sealed, you can do this:
public class CustomerData: WebService.WebServiceClient, ICustomerData
{}
You will need to find a way to supply an implementation of ICustomerData
to your production code so that you can use the actual implementation during production and a fake during the tests, which I talk about right now:
The second problem is that in your test, you're attempting to fake calls to WebServiceClient.CustomerNumber
, which feels like a type to me, not an actual object that you're dealing with. Following along from our step above, you want to fake the ICustomerData
interface:
var fakeCustomerData = A.Fake<ICustomerData>();
var someCustomerName = getACustomerNameSomehow();
A.CallTo(() => fakeCustomerData.GetCustomerName(A<CustomerNumber>.Ignored)
.Returns(someCustomerName);
This will make sure your fake returns someCustomerName
whenever GetCustomerName
is called. I changed someCustomerName
from a fake because you may not need it to be a fake - if it's easy to create a CustomerName
object to return from your fake service, I'd just do that. Only if you need to change its behaviour, or it's almost impossible to create, would I use a fake.
After the fake is configured, you should call some method on your production class (which you said was called CustomerName
, just like the type returned from GetCustomerName
?), that will eventually call the ICustomerData
collaborator. In your original code, you're calling a method on the fake directly, which only tests the fake, not your own code. So instead you might have something like
var customerNameService = new CustomerName(fakeCustomerData);
var foundCustomerName = customerNameService.GetACustomerNameFromANumber(someCustomerNumber);
// in my imagination, GetACustomerNameFromANumber calls ICustomerData.GetCustomerName
// now do something to check if the foundCustomerName is right, or whatever
Upvotes: 1
Reputation: 155
Instead of refering to the webservice directly and hence try to mock the webservice itself, create an interface instead which holds the functionality the webservice provides.
public interface ICustomerData
{
CustomerName GetCustomerName(CustomerNumber number);
}
Then, make two implementations. One which calls the actual webservice, and one which you can use for testing:
public class CustomerData : ICustomerData
{
CustomerName GetCustomerName(CustomerNumber number)
{
return CustomerData.GetCustomerName(number);
}
public CustomerData()
{
CustomerData = new WebService.WebServiceClient ();
}
private WebService.WebServiceClient CustomerData;
}
public class DelegatedCustomerData : ICustomerData
{
public Func<CustomerNumber,CustomerName> GetCustomerName {get;set;}
CustomerName ICustomerData.GetCustomerName(CustomerNumber number) => GetCustomerName(number);
}
The latter delegated class is just an example on how to mock the class, but which i personally prefer.
Upvotes: 2