2

У меня есть класс, который имеет частный конструктор и доступен через общедоступный статический метод (singleton class). Не удалось создать одноэлементный объект этого класса в подделках.Поддельный статический/одиночный класс/метод с использованием подделок microsoft

public class MyBusinessManager : BusinessManager 
{ 
private MyBusinessManager objMyBusinessManager; 

private MyBusinessManager (MyBusinessManager dvqsDataManager) 
     { 
      objMyBusinessManager= dvqsDataManager; 
     } 
public static MyBusinessManager GetInstance() // out 
     { 
      MyBusinessManager dvqsDataMgr = new MyBusinessManager(); 

      return new MyBusinessManager (dvqsDataMgr); 
     } 

public bool MyBusinessManagerMethod (int bm) 
     { 
       if(bm == 0) 
       return true; 

       return false; 
     } 
} 

Я хочу проверить следующий метод:

public class MyService 
{ 
    public bool MyServiceMethod(int serviceParam) 
    { 
     MyBusinessManager dvqBusinessManager = MyBusinessManager.GetInstance(); // make fake call 
     return dvqBusinessManager.MyBusinessManagerMethod(serviceParam); // make fake service call 
    } 
} 

Мой тест Класс:

[TestClass] 
public class MyService_UT 
{ 
    [TestMethod] 
    public void TestMethod1() 
    { 
     using (ShimsContext.Create()) 
     { 
     ShimMyBusinessManager.GetInstance =() => { return new ShimMyBusinessManager(); }; 
     ShimMyBusinessManager.AllInstances.MyServiceMethodInt32 = (a) =>{ 
           return true; 
           } 
     MyService obj = new MyService(); 
     Assert.IsTrue(obj.MyServiceMethod(1))// doesn't call fake method 
     } 
    } 
} 

Как назвать фальшивый метод в этом случае? Невозможно создать экземпляр подделки с этим кодом.

+3

Вы только что узнали одну из причин, по которой одиночные игры - это «анти-шаблон». – Joe

+0

Исправить. Это старый код. Но как выйти из этого? – user2323308

+1

Возможно, было бы проще реорганизовать дрянной старый код вместо того, чтобы поместить еще один слой дерьмового кода сверху, чтобы проверить его. – nvoigt

ответ

1

Предлагаю переместить создание dvqBusinessManager вне метода.

Таким образом

MyBusinessManager dvqBusinessManager = MyBusinessManager.GetInstance(); 
    public bool MyServiceMethod(int serviceParam) 
    { 
     return dvqBusinessManager.MyBusinessManagerMethod(serviceParam); // make fake service call 
    } 

Или

public bool MyServiceMethod(int serviceParam) 
    { 
     MyBusinessManager dvqBusinessManager = MyBusinessManager.GetInstance(); 
     MyServiceTestableMethod(dvqBusinessManager, serviceParam); 
    } 

    public bool MyServiceTestableMethod(MyBusinessManager manager, int serviceParam) 
    { 
     return manager.MyBusinessManagerMethod(serviceParam); 
    } 

Таким образом, вы можете придать поддельный объект в метод и проверить его, не вызывая GetInstance метод.

Или вы можете реализовать и использовать шаблон фабрики и скрыть статический вызов там.

public interface IServiceFactory 
    { 
     MyBusinessManager GetInstance(); 
    } 

    public class ServiceFactory : IServiceFactory 
    { 
     public MyBusinessManager GetInstance() 
     { 
      return MyBusinessManager.GetInstance(); 
     } 
    } 

    IServiceFactory factory = new ServiceFactory(); 
    public bool MyServiceMethod(int serviceParam) 
    { 
     MyBusinessManager dvqBusinessManager = factory.GetInstance(); 
     dvqBusinessManager.MyBusinessManagerMethod(serviceParam); 
    } 

Но если вы все еще хотите, чтобы дразнить статический вызов без изменения кода, вы должны использовать Проставки как в этом примере http://www.richonsoftware.com/post/2012/04/05/using-stubs-and-shim-to-test-with-microsoft-fakes-in-visual-studio-11.aspx.

+0

Спасибо. Я использовал код, упомянутый в ссылке, для решения этой проблемы. – user2323308