I have a WCF Service:
[ServiceTelemetry]
public class MyWCFClass()
{
private TelemetryClient telemetryClient;
public MyWCFClass()
{
telemetryClient = new TelemetryClient()
{
InstrumentationKey = RoleEnvironment.GetConfigurationSettingValue("APPINSIGHTS_INSTRUMENTATIONKEY")
};
}
public string TheMethod()
{
return "Nice";
}
}
Works like a charm. Now I want to unit test this WCF service:
[TestMethod()]
public void DoTest()
{
MyWCFClass theClass = new MyWCFClass();
Assert.AreEqual("Nice", theClass.TheMethod());
}
My problem is, that when I run the test, an SEH exception occurs on the constructor of the WCFClass.
Is there any way to fake the RoleEnvironment part or skip the telemetry part?
Related
I have created a very simple server and client console app demonstrating the issue I have in that I am trying to bring an instance of a serializable object across to the client but it fails on the server.
What am I missing?? I am NOT concerned right now having it Service orientated using DataContracts - I am simply trying to understand why the code as it stands doesn't bring the EJob accross to the client (it DOES however calls the 'Hello from the server' message)
Many thanks.
EDIT
Even if I decorate the EJob class with a DataContract attribute (like below) it STILL doesn't work - the object I receive on the client has LastName set to null?????
[DataContract]
public class EJob
{
[DataMember]
public string LastName = "Smith";
}
SERVER
namespace testServer
{
[ServiceContract()]
public interface IRemoteClient
{
[OperationContract]
void SayHi(string msg);
[OperationContract]
void ProcessJob(EJob job);
}
[Serializable()]
public class EJob
{
public string LastName = "Smith";
}
class Program
{
static void Main(string[] args)
{
MngrServer.SendJob();
}
}
public class MngrServer
{
public static void SendJob()
{
try
{
// send this off to the correct exe
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None, true);
string address = string.Format("net.tcp://localhost:33888/BatchMananger/client");
EndpointAddress epa = new EndpointAddress(address);
// create the proxy pointing to the correct exe
IRemoteClient clientProxy = ChannelFactory<IRemoteClient>.CreateChannel(binding, epa);
clientProxy.SayHi("Hello from server"); <-- THIS WORKS FINE
EJob job = new EJob { LastName = "Janssen" };
clientProxy.ProcessJob(job); <-- THIS RAISES AN EXCEPTION see below...
}
catch (Exception ex)
{
string msg = ex.Message;
//The formatter threw an exception while trying to deserialize the message: There was an error while
//trying to deserialize parameter http://tempuri.org/:job. The InnerException message was ''EndElement' 'job'
//from namespace 'http://tempuri.org/' is not expected. Expecting element 'LastName'.'.
}
}
}
}
CLIENT
namespace testClient
{
[ServiceContract()]
public interface IRemoteClient
{
[OperationContract]
void SayHi(string msg);
[OperationContract]
void ProcessJob(EJob job);
}
[Serializable()]
public class EJob
{
public string LastName = "Smith";
}
class Program
{
static void Main(string[] args)
{
MngrClient.Prepare();
Console.ReadLine();
}
}
/// <summary>
/// STATIC / INSTANCE
/// </summary>
public class MngrClient : IRemoteClient
{
public void SayHi(string msg)
{
Console.WriteLine(msg);
}
public void ProcessJob(EJob job)
{
Console.WriteLine(job.LastName);
}
public static void Prepare()
{
// allow this class to be used! - so instances are created and info directly passed on to its static members.
ServiceHost sh = new ServiceHost(typeof(MngrClient));
// create the net binding
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None, true);
// define the tcpaddress
string address = string.Format("net.tcp://localhost:33888/BatchMananger/client");
// add a service point so my server can reach me
sh.AddServiceEndpoint(typeof(IRemoteClient), binding, address);
// now open the service for business
sh.Open();
}
}
}
Your EJob datacontract is in a different namespace on the server vs. the client. You need to either declare both classes in the same namespace, or use attributes to set the namespace on the client to match the namespace on the server
(Either the Datacontract attribute has a namespace value that you can pass, or there is a separate namespace attribute that you can use to tell WCF to use an alternate namespace for the contract, can't remember off the top of my head)
EDIT
Just verified -- it's the Namespace property of the DataContractAttribute that you want, so in your client-side declaration:
[DataContract(Namespace="EJobNamespaceAsItIsDeclaredOnTheServer")]
public class EJob ...
Now, it is very common to put all of your DataContracts in a separate assembly (called a contract assembly) that is referenced by both the client and the server. You would want just the contract class definitions in that assembly, nothing else.
You somehow have it all a bit backwards...
given your service contract of IRemoteClient, you should then have an implementation class on the server-side that implements that interface:
public class ServiceImplementation : IRemoteClient
{
public void SayHi(string msg)
{
.....
}
public void ProcessJob(EJob job)
{
.....
}
}
Also: the service methods should be returning something to the caller! Without a return type, you're kinda creating a black-hole of a service - you can call its methods, but nothing gets returned.... Plus: the service implementation class should NOT be hosting itself! Make that a separate class
you should then have a host class on the server side that hosts this service:
public class HostForYourService
{
public HostForYourService()
{
// send this off to the correct exe
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None, true);
string address = string.Format("net.tcp://localhost:33888/BatchMananger/client");
EndpointAddress epa = new EndpointAddress(address);
ServiceHost sh = new ServiceHost(typeof(ServiceImplementation));
// define the tcpaddress
sh.AddServiceEndpoint(typeof(IRemoteClient), binding, address);
// now open the service for business
sh.Open();
}
and then your client should build the client-side proxy for this service and call it
public class YourServiceClient
{
public void CallService()
{
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None, true);
string address = string.Format("net.tcp://servername:33888/BatchMananger/client");
EndpointAddress epa = new EndpointAddress(address);
// create the proxy pointing to the correct exe
IRemoteClient clientProxy = ChannelFactory<IRemoteClient>.CreateChannel(binding, epa);
clientProxy.SayHi("Hello from server"); <-- THIS WORKS FINE
EJob job = new EJob { LastName = "Janssen" };
clientProxy.ProcessJob(job);
}
}
But again: typically, your service methods should be returning something that the client can then operate on - after all, you typically don't want to do a Console.WriteLine on the server - you want to compute something, look up something etc. and return a response to the client which then in turns can e.g. output the result to the console or something....
I'm having a really hard time trying to figure how I can do .SetupXXX() calls on the underlying Mock<T> that has been generated inside the MockingKernel. Anyone who can shed some light on how it is supposed to work?
You need to call the GetMock<T> method on the MoqMockingKernel which will return the generated Mock<T> on which you can call your .SetupXXX()/VerifyXXX() methods.
Here is an example unit test which demonstrates the GetMock<T> usage:
[Test]
public void Test()
{
var mockingKernel = new MoqMockingKernel();
var serviceMock = mockingKernel.GetMock<IService>();
serviceMock.Setup(m => m.GetGreetings()).Returns("World");
var sut = mockingKernel.Get<MyClass>();
Assert.AreEqual("Hello World", sut.SayHello());
}
Where the involved types are the following:
public interface IService { string GetGreetings(); }
public class MyClass
{
private readonly IService service;
public MyClass(IService service) { this.service = service; }
public string SayHello()
{
return string.Format("Hello {0}", service.GetGreetings());
}
}
Note that you can access the generated Moq.MockRepository (if you prefer it over the SetupXXX methods) with the MoqMockingKernel.MockRepository property.
I'm working with an application which uses wcf and sharp architecture, I'm trying to create a service to write to the database. Here is my service: (Sicaf.Core.Services.Wcf)
[ServiceContract]
public interface IFacturaWcfService : ICloseableAndAbortable
{
[OperationContract]
string ConsultarValorMatricula(string xmlData);
}
[ServiceBehavior, AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class FacturaWcfService : IFacturaWcfService
{
private readonly IFacturaBusiness facturaBusiness;
public FacturaWcfService(IFacturaBusiness facturaBusiness)
{
this.facturaBusiness = facturaBusiness;
}
public string ConsultarValorMatricula()
{
return facturaBusiness.GetFactura();
}
public void Abort() { }
public void Close() { }
}
In the ComponentRegistrar.cs: (Sicaf.Core.Services.WebServices)
private static void AddWcfServicesTo(IWindsorContainer container)
{
// Since the TerritoriesService.svc must be associated with a concrete class,
// we must register the concrete implementation here as the service
container.AddComponent("facturaWcfService", typeof(FacturaWcfService));
}
I created a client but I get this exception:
The needed dependency of type FacturaWcfService could not be located with the ServiceLocator. You'll need to register it with the Common Service Locator (CSL) via your IoC's CSL adapter.
I've finally found my mistake.
Before:
private static void AddCustomRepositoriesTo(IWindsorContainer container)
{
// Register Data Layer Services
container.Register(
AllTypes.Pick()
.FromAssemblyNamed("Sicaf.Core.Services.Data")
.WithService.FirstNonGenericCoreInterface("Sicaf.Core.Services.Services.Data"));
}
After:
private static void AddCustomRepositoriesTo(IWindsorContainer container)
{
// Register Data Layer Services
container.Register(
AllTypes.Pick()
.FromAssemblyNamed("Sicaf.Core.Services.Data")
.WithService.FirstNonGenericCoreInterface("Sicaf.Core.Services.Services.Data"));
container.Register(
AllTypes.Pick()
.FromAssemblyNamed("SismatV2.Data")
.WithService.FirstNonGenericCoreInterface("SismatV2.Services.Data"));
}
Hopefully this is an easy one. I'm wondering if this is possible - perhaps it is not. I'm attempting to self-host a WCF service (in my example below it is a console application). The service does not have a default constructor. It only contains a single parameter signature constructor. I need the service to be able to handle user sessions. Currently I am using Ninject DI. Here is a simple code solution I came up with to demonstrate my issue:
using System;
using System.ServiceModel;
using System.ServiceModel.Web;
using Ninject.Modules;
namespace ConsoleApplication1
{
public class Program
{
static void Main()
{
using (var webServiceHost = new WebServiceHost(typeof(MyWcf)))
{
var webHttpBinding = new WebHttpBinding();
var uri = new Uri("http://localhost:8000/");
webServiceHost.AddServiceEndpoint(typeof(IMyWcf), webHttpBinding, uri);
webServiceHost.Open();
Console.WriteLine("Service is ready...");
Console.ReadKey();
}
}
}
[ServiceContract]
public interface IMyWcf
{
[OperationContract, WebGet(UriTemplate = "")]
string HelloWorld();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MyWcf : IMyWcf
{
private readonly IMessage _customMessage = new Message("Default Message.");
public MyWcf(IMessage message)
{
_customMessage = message;
}
public string HelloWorld()
{
return _customMessage.Text;
}
}
public interface IMessage
{
string Text { get; }
}
public class Message : IMessage
{
public Message (string message)
{
Text = message;
}
public string Text { get; set; }
}
public class NinjectSetup : NinjectModule
{
public override void Load()
{
Bind<IMessage>().To<Message>()
.WithConstructorArgument("message", "Injected String Message.");
}
}
}
Obviously commenting out the parameterized constructor allows the service to run. But that does me no good. I don't want to use ServiceHostFactory because that apparently requires me to have a .svc/IIS. Is there a way around this? Can I just create a new MyWebServiceHost that inherits from WebServiceHost and override some method that will create a instance for the service?
Using Ruben's suggestion (in the comments) above, I was able to locate a working example within the Ninject.Extensions.Wcf source repository.
I have a service proxy class that makes asyn call to service operation. I use a callback method to pass results back to my view model.
Doing functional testing of view model, I can mock service proxy to ensure methods are called on the proxy, but how can I ensure that callback method is called as well?
With RhinoMocks I can test that events are handled and event raise events on the mocked object, but how can I test callbacks?
ViewModel:
public class MyViewModel
{
public void GetDataAsync()
{
// Use DI framework to get the object
IMyServiceClient myServiceClient = IoC.Resolve<IMyServiceClient>();
myServiceClient.GetData(GetDataAsyncCallback);
}
private void GetDataAsyncCallback(Entity entity, ServiceError error)
{
// do something here...
}
}
ServiceProxy:
public class MyService : ClientBase<IMyService>, IMyServiceClient
{
// Constructor
public NertiAdminServiceClient(string endpointConfigurationName, string remoteAddress)
:
base(endpointConfigurationName, remoteAddress)
{
}
// IMyServiceClient member.
public void GetData(Action<Entity, ServiceError> callback)
{
Channel.BeginGetData(EndGetData, callback);
}
private void EndGetData(IAsyncResult result)
{
Action<Entity, ServiceError> callback =
result.AsyncState as Action<Entity, ServiceError>;
ServiceError error;
Entity results = Channel.EndGetData(out error, result);
if (callback != null)
callback(results, error);
}
}
Thanks
Played around with this a bit and I think I may have what you're looking for. First, I'll display the MSTest code I did to verify this:
[TestClass]
public class UnitTest3
{
private delegate void MakeCallbackDelegate(Action<Entity, ServiceError> callback);
[TestMethod]
public void CallbackIntoViewModel()
{
var service = MockRepository.GenerateStub<IMyServiceClient>();
var model = new MyViewModel(service);
service.Stub(s => s.GetData(null)).Do(
new MakeCallbackDelegate(c => model.GetDataCallback(new Entity(), new ServiceError())));
model.GetDataAsync(null);
}
}
public class MyViewModel
{
private readonly IMyServiceClient client;
public MyViewModel(IMyServiceClient client)
{
this.client = client;
}
public virtual void GetDataAsync(Action<Entity, ServiceError> callback)
{
this.client.GetData(callback);
}
internal void GetDataCallback(Entity entity, ServiceError serviceError)
{
}
}
public interface IMyServiceClient
{
void GetData(Action<Entity, ServiceError> callback);
}
public class Entity
{
}
public class ServiceError
{
}
You'll notice a few things:
I made your callback internal. You'll need to use the InternalsVisisbleTo() attribute so your ViewModel assembly exposes internals to your unit tests (I'm not crazy about this, but it happens in rare cases like this).
I use Rhino.Mocks "Do" to execute the callback whenever the GetData is called. It's not using the callback supplied, but this is really more of an integration test. I assume you've got a ViewModel unit test to make sure that the real callback passed in to GetData is executed at the appropriate time.
Obviously, you'll want to create mock/stub Entity and ServiceError objects instead of just new'ing up like I did.