Как провести рефакторинг метода для замены OrganizationServiceProxy на IOrganizationService

Я пытаюсь реорганизовать свой код, чтобы выполнить модульное тестирование с использованием fakexrmeasy.

Как часть предложенного рефакторинга, упомянутого здесь, я попытался передать IOrganizationService во все мои классы и методы. Тем не менее, некоторые из моих классов используют переменные и методы, которых нет у IOrganizationService, например Timeout. Я пытаюсь найти способ рефакторинга для использования IOrganizationService без потери функциональности.

Вот как это существует до рефакторинга.

class testClass () {

    public void testMethod(OrganizationServiceProxy service) {
        service.Timeout = new TimeSpan(0, 15, 0);
    }

}

Это после рефакторинга. Я попытался привести IOrganizationService к OrganizationServiceProxy, но поддельный контекст службы не может обработать это приведение. Исключение брошено.

class testClass () {

    public void testMethod(IOrganizationService service) {
        var serviceProxy = (OrganizationServiceProxy) service; //This breaks when given a fake context
        service.Timeout = new TimeSpan(0, 15, 0);
    }

}

Я попытался использовать IOrganizationServiceFactory, как предлагается в этом посте. Проблема заключается в том, что factory.CreateOrganizationService() создает IOrganizationService, а не OrganizationSeriviceProxy.

Как я могу реорганизовать использование IOrganizationService вместо OrganizationServiceProxy без потери функциональности? Я предполагаю, что мне, возможно, придется каким-то образом реализовать IOrganizationService в качестве OrganizationServiceProxy.

3 ответа

Два варианта:

1) Чтобы не усложнять, реорганизуйте свой код так, чтобы он ссылался только на IOrganizationService, и используйте только этот код в своих тестах, и оставьте бит TimeOut непроверенным (вне области рефакторинга функций)

2) Если модульное тестирование свойства Timeout действительно необходимо, имитируйте свой собственный класс OrganizationServiceContext и передайте фиктивный сервис, созданный FakeXrmEasy (IOrganizationService), в конструктор OrganizationServiceProxy. Вот список всех доступных конструкторов:

https://docs.microsoft.com/en-us/dotnet/api/microsoft.xrm.sdk.client.organizationserviceproxy.-ctor?view=dynamics-general-ce-9

Я не уверен, что это поможет, но это то, что я использовал

CrmServiceClient c = new CrmServiceClient(connectionstring); //various parameters available
(OrganizationServiceProxy) service = c.OrganizationWebProxyClient ?? c.OrganizationServiceProxy;

Может ли что-то подобное быть жизнеспособным?

public class OrganizationServiceProxy : IServiceProxy
  {
    public int SomeProp
    {
      get
      {
        return 1;
      }

      set
      {
      }
    }

    public TimeSpan Timeout
    {
      get
      {
        return new TimeSpan();
      }

      set
      {
      }
    }

    public void SomeMethod()
    {
    }
  }
  public interface IServiceProxy : IOrganizationService
  {
    TimeSpan Timeout { get; set; }
  }

  public interface IOrganizationService
  {
    void SomeMethod();
    int SomeProp { get; set; }
  }

Поскольку OrganizationServiceProxy реализует IServiceProxy (который, в свою очередь, реализует IOrganizationService), вы можете проверить, реализует ли переданный вами объект интерфейс IServiceProxy, и выполнить свою работу внутри if.

private void testMethod(IOrganizationService someService)
{
   if(someService is IServiceProxy)
   {
     IServiceProxy tempProxy = someService as IServiceProxy;
     tempProxy.Timeout = new TimeSpan();
   }
}

Я думаю, что есть простое решение - если вам не нужно издеваться над методами OrganizationServiceProxy - просто игнорируйте это в контексте модульного тестирования.

IE вместо

// This breaks when given a fake context
var serviceProxy = (OrganizationServiceProxy) service;
serviceProxy.Timeout = new TimeSpan(0, 15, 0);

Делать

var serviceProxy = service as (OrganizationServiceProxy);
// The serviceProxy is null so it is ignored when given a fake context
if (serviceProxy != null)
{
   serviceProxy.Timeout = new TimeSpan(0, 15, 0);
}
Другие вопросы по тегам