Visual Studio 単体テストで WCF サービスを試しています。クライアントとサービスの両方がプログラムで構成されます。
現在、私のコードは次のようになっています。
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Tests
{
public abstract class EntityBase
{
}
public class TestEntity : EntityBase
{
public string Name { get; set; }
}
[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(ServiceKnownTypesDiscoveryHelper))]
public interface ITestService
{
[OperationContract]
EntityBase GetEntity(string entityName);
}
public class TestService : ITestService
{
public EntityBase GetEntity(string entityName)
{
Type t = Type.GetType(entityName);
return (EntityBase)Activator.CreateInstance(t);
}
}
[TestClass]
public class ServiceTests
{
private static ServiceHost ServiceHost { get; set; }
[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
{
ServiceHost = new ServiceHost(typeof(TestService));
NetTcpBinding wsBinding = new NetTcpBinding();
ServiceHost.AddServiceEndpoint(typeof(ITestService), wsBinding,
"net.tcp://localhost:8011/TestService");
// trying to turn on debugging here
var behavior = ServiceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
behavior.IncludeExceptionDetailInFaults = true;
ServiceHost.Open();
}
[ClassCleanup]
public static void ClassCleanup()
{
ServiceHost.Close();
}
[TestMethod]
public void TestSomething()
{
var binding = new NetTcpBinding();
var endpoint = new EndpointAddress("net.tcp://localhost:8011/TestService");
using (ChannelFactory<ITestService> testServiceFactory =
new ChannelFactory<ITestService>(binding, endpoint))
{
var proxy = testServiceFactory.CreateChannel();
using (proxy as IDisposable)
{
try
{
var entity = proxy.GetEntity(typeof(TestEntity).FullName);
Assert.IsInstanceOfType(entity, typeof(TestEntity));
}
catch (FaultException ex)
{
// copied this from MSDN example
string msg = "FaultException: " + ex.Message;
MessageFault fault = ex.CreateMessageFault();
if (fault.HasDetail == true)
{
var reader = fault.GetReaderAtDetailContents();
if (reader.Name == "ExceptionDetail")
{
ExceptionDetail detail = fault.GetDetail<ExceptionDetail>();
msg += "\n\nStack Trace: " + detail.StackTrace;
}
}
System.Diagnostics.Trace.WriteLine(msg);
}
}
}
}
}
}
ServiceKnownTypesDiscoveryHelper が既知の型を返さない場合、サービスとクライアントが .NET servicemodel コードのどこかでシリアル化に関連する何かをスローする必要があることがわかっています (TestEntity を返すように変更すると、もちろんすべて問題なく動作します)。
しかし、現在、サービスが失敗した場合、次のような漠然とした例外メッセージしか表示されません。
The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue.
そして using() の最後に私は得る
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
(これも奇妙です-ServiceChannelが障害状態にある場合、なぜServiceChannelを破棄できないのですか...)
これらのあいまいな例外メッセージの代わりに、サービスまたはクライアントが失敗する原因となった実際の障害をキャッチするにはどうすればよいですか?