Reputation: 16831
I've implemented an ASP.net Web Service SoapExtension
and I want to unit test it. Trouble is I have code in the ProcessMessage()
method that I want to test and this method expects a SoapMessage
as an argument.
Given than SoapMessage
is an abstract class with an internal constructor and that the only two derived classes that I know (SoapClientMessage
and SoapServerMessage
) are sealed, how can I instantiate it?
Is my only option to use commercial mocking tools like TypeMock or JustMock?
Upvotes: 2
Views: 234
Reputation: 16831
Best I could come up with is using reflection to instantiate the sealed classes and set values in their internal fields.
Here is the code that I came up with:
private SoapServerMessage CreateSoapServerMessage(
SoapMessageStage stage,
string action,
SoapHeaderCollection headers)
{
var typ = typeof(SoapServerMessage);
// Create an instance:
var constructorInfo = typ.GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null, new[] { typeof(SoapServerProtocol) }, null);
var message = (SoapServerMessage)constructorInfo.Invoke(new object[] { CreateSoapServerProtocol(action) });
// Set stage:
var stageField = typ.BaseType.GetField("stage", BindingFlags.NonPublic | BindingFlags.Instance);
stageField.SetValue(message, stage);
// Set headers:
var headersField = typ.BaseType.GetField("headers", BindingFlags.NonPublic | BindingFlags.Instance);
headersField.SetValue(message, headers);
return message;
}
private SoapServerProtocol CreateSoapServerProtocol(string action)
{
var typ = typeof(SoapServerProtocol);
// Create an instance:
var constructorInfo = typ.GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null, Type.EmptyTypes, null);
var protocol = (SoapServerProtocol)constructorInfo.Invoke(null);
// Set serverMethod:
var serverMethodField = typ.GetField("serverMethod", BindingFlags.NonPublic | BindingFlags.Instance);
serverMethodField.SetValue(protocol, CreateSoapServerMethod(action));
return protocol;
}
private SoapServerMethod CreateSoapServerMethod(string action)
{
var typ = typeof(SoapServerMethod);
// Create an instance:
var method = new SoapServerMethod();
// Set action:
var actionField = typ.GetField("action", BindingFlags.NonPublic | BindingFlags.Instance);
actionField.SetValue(method, action);
return method;
}
Upvotes: 1