Kash Farooq's software development blog

.NET Developer

Mocking WCF Services with Rhino Mocks

Posted by Kash Farooq on November 29, 2008

With WCF self-hosting it is easy to substitute an external service dependency with a mock service.
If you have code that calls an external web service, and you want to create an integration test that ensures that the external web service is called with the correct data, you can combine WCF self-hosting and a mocking framework to replace the external web service.
First, let’s create a pretend external web service that has one method that receives a complex type.

namespace TheService
{
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        Acknowledgement SubmitOrder(Order order);
    }

    [DataContract]
    public class Order {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public IList OrderLines { get; set; }
    }

    [DataContract]
    public class OrderLine {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string Description { get; set; }
    }
}

The system under test uses this web service:

namespace TheClient {
    public class Facade {
        public bool SubmitOrder() {
            var order=new Order();
            order.Id = 1;
            order.OrderLines=new List();
            order.OrderLines.Add(new OrderLine{Description = "OrderLine1",Id = 1});
            order.OrderLines.Add(new OrderLine{Description = "OrderLine2",Id = 2});
            Acknowledgement acknowledgement;
            using (var serviceClient=new ServiceClient()) {
                acknowledgement = serviceClient.SubmitOrder(order);
            }
            return acknowledgement.Success;
        }
    }
}

Now we can write an integration test that makes sure we call the service with two order lines. First I create a class that implements the service contract. The methods do not need to be implemented as we will use Rhino Mocks to mock the behaviour – however notice that I had to make the method virtual so that I can use PartialMock. Also note the InstanceContextMode. It needs to set to “single” so that a mock service object can be loaded by ServiceHost.

namespace IntegrationTests {
   [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class PartialMockService : IService {
        public virtual Acknowledgement SubmitOrder(Order order) {
            throw new NotImplementedException();
        }
    }
}

Now I can create the test. The mock needs to be set up in the TestFixtureSetup so that the service is running throughout all the tests.
The test sets up expectations on the service mock, and checks the arguments that were sent to the service method.

    [TestFixture]
    public class PartialMockTheService {
        private ServiceHost host;
        private MockRepository mockRepository;
        private PartialMockService serviceMock;

        [TestFixtureSetUp]
        public void TestFixtureSetUp() {
            mockRepository = new MockRepository();
            serviceMock = mockRepository.PartialMock<PartialMockService>();
            host = new ServiceHost(serviceMock);
            host.AddServiceEndpoint(typeof (IService), new BasicHttpBinding(), "http://localhost:8093/Service.svc");
            host.Open();
        }

        [Test]
        public void FacadeShouldCallTheWebserviceWithTwoOrderLines() {
            serviceMock.Expect(x => x.SubmitOrder(new Order()))
                            .IgnoreArguments()
                            .Return(new Acknowledgement {Success = true});
            mockRepository.ReplayAll();
            var facade = new Facade();

            Assert.IsTrue(facade.SubmitOrder());
            IList argumentsForCallsMadeOn = serviceMock
                              .GetArgumentsForCallsMadeOn(x => x.SubmitOrder(null));
            var order = (Order) argumentsForCallsMadeOn[0][0];
            Assert.AreEqual(2, order.OrderLines.Count);
        }
    }
}

The unit test app.config needs the same Service Model confiuration settings as the system under test, with the service location altererd so that it points to your mock rather than the real service.

<system.serviceModel>
        <client>
            <endpoint
                    address="http://localhost:8093/Service.svc"
                    binding="basicHttpBinding"
                    contract="TheServiceProxy.IService" />
      </client>
</system.serviceModel>

I tried to do the same test but with DynamicMock rather than PartialMock. If you can get this to work you save some code as you won’t need to create PartialMockService. However, I could not get this to work. I got the error:

The service class of type IServiceProxyc688097f68fa4881a2eac45ad09283ba both defines a ServiceContract and inherits a ServiceContract from type TheService.IService. Contract inheritance can only be used among interface types. If a class is marked with ServiceContractAttribute, it must be the only type in the hierarchy with ServiceContractAttribute.

Basically, it appears as though the ServiceContract attribute is on both interface and dynamically created concrete. I did some brief investigation and I don’t think the problem is inside Rhino Mocks – I think it is in Castle’s DymanicProxy code that Rhino Mocks uses.

Related Posts

Stubbing RESTful services with WCF

Advertisements

One Response to “Mocking WCF Services with Rhino Mocks”

  1. Sebastian said

    probably you already know about this, but now you can use AttributesToAvoidReplicating.Add(typeof(blaAttribute)) to get around this

Sorry, the comment form is closed at this time.

 
%d bloggers like this: