简体   繁体   中英

Mock service without interfaces using rhino mocks

Background My application is consuming a WCF service via proxyies. I have to unit test my implementation, that it consume the service and processing are done correctly.

Method to be Tested

public class MyClass
{ 
 private ManagerServiceClientImpl myclient;

 public void MethodToBeTested();
 {
    var result = GetServiceData();
    if(result!=null)
       //some processing
 }
}

private MyObject GetServiceData()
{
    myclient = ServiceLocator.Current.GetInstance<ManagerServiceClientImpl>();
    if(myclient.ConnectToService() && myclient.MyServiceClient.IsConnected)
       return myclient.GetData();
    else
     return null;
}

This is provided by external source, so I have no right to modify it

public class ManagerServiceClientImpl
{
  public ServiceClient MyServiceClient { get; private set; }
  public bool ConnectToService()
}

How would I mock the ManagerServiceClientImpl it doesn't have interface or methods are not marked as virtual

What i tried so far.

[TestMethod]
public void IsServiceConnected_GetData()
{

  //Arrange
  ManagerServiceClientImpl clientImpl = 
               MockRepository.GenerateMock<ManagerServiceClientImpl>();

  ServiceLocator.Expect(x => x.GetInstance<ManagerServiceClientImpl>())
                .Return(clientImpl);

  var testData= new MyObject 
  {
            ID = "Test1",
            Name ="test",
  }

  //Act
  _myClass.MethodToBeTested();

  //Assert
  stubService.AssertWasCalled(h => h.SaveAllChanges());
}

Note: Using Rhino.Mocks. Its my first time using Rhino mocks

As Amittai Shapira mentioned you can mock it without an interface by using unit testing frameworks that support it, i'm using Typemock Isolator and i created an example test for your code:

I've created an instance of MyClass and used a feature of Typemock to mock Non-Public methods to change the return value for GetServiceData

[TestMethod]
public void TestMethod1()
{
    var testData = new MyObject
    {
        ID = "Test1",
        Name = "test",
    };

    var realObj = new MyClass();
    Isolate.NonPublic.WhenCalled(realObj, "GetServiceData").WillReturn(testData);
    Isolate.NonPublic.WhenCalled(realObj, "SaveAllChanges").CallOriginal();

    realObj.MethodToBeTested();

    Isolate.Verify.NonPublic.WasCalled(realObj, "SaveAllChanges");
}

In order to use RhinoMocks (or Moq, or any other "constrained" mocking framework), the type you are mocking must support inheritance on the members you want to mock. This means it must either be an interface, or the members must be virtual/abstract. Without that, these frameworks cannot do what they need to do to generate a proxy middle-man at runtime. For more details, see my blog post on how .NET mocking frameworks work under the hood: https://www.wrightfully.com/how-net-mocking-frameworks-work

What you could do is create methods in your own class that wrap the other service such that you could mock your methods and have them return whatever you need, completely bypassing the service.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM