I have been tasked with automating tests for a webservice. Pretty straight forward. What I did was:
- Add service reference in my project.
- Write code to execute tests with MSTest unit test framework. While doing this, realize the service is not. Um. Entirely tight. I had to make some changes to Reference.cs to handle responses which are defined in the wsdl as having datetime values but are not present. Keep track of changes so when I have to reload the wsdl, I will know what I have changed. Don’t love. Don’t see alternative. Should not be relevant.
- Finish creating tests for several of the endpoints in the service.
Get to one which is yielding behavior I do not understand. What I observe when testing what I wrote.
When I run the test which includes the new service call, I receive an error:
Message:
Test method CcbWebServicesTestingNet.TestDevelopment.AddCustmerDonorConsent threw exception:
System.ServiceModel.FaultException: Parameter contactCustomerResponse in method AddCustomerDonorConsent in service CustomerManagement is null!
Relevant troubleshooting info:
- Run the same endpoint in SOAPUI with the same inputs. Returns response properly. Cool problem is in my code, of course.
- Test my code with fiddler open. When I get to the bad call, see
Ok unauthorized. Exact same authorization code. And … why is NULL response coming back from my call instead of an auth error as with when I change the user name to user name plus some random characters to demonstrate failure. When I change the user name to something clearly invalid and run a working test, I receive this error:
Test method CcbWebServicesTestingNet.TestDevelopment.AddCustmerDonorConsent threw exception:
System.ServiceModel.Security.MessageSecurityException: The HTTP request is unauthorized with client authentication scheme ‘Ntlm’. The authentication header received from the server was ‘NTLM’. —> System.Net.WebException: The remote server returned an error: (401) Unauthorized.
The code that does the auth work is in this class for the ContactCustomer client type.
using System.ServiceModel;
using CcbWebServicesTestingNet.ServiceRefCreditCard;
using CcbWebServicesTestingNet.ServiceRefCustomerManagement;
using CcbWebServicesTestingNet.ServiceRefDonor;
namespace CcbWebServicesTestingNet.Model
{
public static class ComponentClient
{
private enum ClientType
{
ContactCustomer,
CustomerCreditCard,
Donor
}
private static BasicHttpBinding _binding;
private static EndpointAddress _address;
private static readonly Settings Settings = new Settings();
public static CustomerCreditCard_PortClient GetClientCreditCardClient()
{
SetParameters(ClientType.CustomerCreditCard);
CustomerCreditCard_PortClient client = new CustomerCreditCard_PortClient(_binding, _address);
if (client.ClientCredentials != null)
{
client.ClientCredentials.Windows.ClientCredential.Domain = Settings.AuthDomain;
client.ClientCredentials.Windows.ClientCredential.UserName = Settings.AuthUserName;
client.ClientCredentials.Windows.ClientCredential.Password = Settings.AuthPassword;
}
return client;
}
public static Donor_PortClient GetClientDonorClient()
{
SetParameters(ClientType.Donor);
Donor_PortClient client = new Donor_PortClient(_binding, _address);
if (client.ClientCredentials != null)
{
client.ClientCredentials.Windows.ClientCredential.Domain = Settings.AuthDomain;
client.ClientCredentials.Windows.ClientCredential.UserName = Settings.AuthUserName;
client.ClientCredentials.Windows.ClientCredential.Password = Settings.AuthPassword;
}
return client;
}
public static CustomerManagement_PortClient GetContactCustomerClient()
{
SetParameters(ClientType.ContactCustomer);
CustomerManagement_PortClient client = new CustomerManagement_PortClient(_binding, _address);
if (client.ClientCredentials != null)
{
client.ClientCredentials.Windows.ClientCredential.Domain = Settings.AuthDomain;
client.ClientCredentials.Windows.ClientCredential.UserName = Settings.AuthUserName;
client.ClientCredentials.Windows.ClientCredential.Password = Settings.AuthPassword;
}
return client;
}
private static void SetParameters(ClientType clientType)
{
string url;
switch (clientType)
{
case ClientType.CustomerCreditCard:
url = Settings.CreditCardUrl;
break;
case ClientType.Donor:
url = Settings.DonorUrl;
break;
default:
url = Settings.CustomerManagementUrl;
break;
}
_binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);
// Configure transport security
_binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
_binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Ntlm;
_binding.Security.Transport.Realm = "";
// Configure message security
_binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
_binding.MaxReceivedMessageSize = 65536 * 2;
_address = new EndpointAddress(url);
}
}
}
Does anyone have suggestions for what I can look at for troubleshooting? This is new work for me, doing SOAP automation. So don’t assume I know stuff. Any suggestions welcome. Thanks!