0
votes

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

2
Wrap 3 rd party dependencies in an abstraction you control in your code and would be able to modify and mock. Avoid service locator anti-pattern which makes the code difficult to test as you have already discovered. This is a design issue.Nkosi
Can u provide an exampleEldho
First you need to clarify the method to be tested as your example is unclear.Nkosi
I didn't understand you fully MethodToBeTested(); is to be tested. The logic in the method is very small. If the service data is not in inventory add to the inventory. Im not sure is this what you asking for. pardon my enlgish `Eldho
Check your small example and see if it even compiles. this is not a minimal reproducible example. The code you have tried so far also refers to methods that are not even indicated in the method under test. You see what I mean right?Nkosi

2 Answers

4
votes

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");
}
2
votes

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.