2016-02-09 2 views
4

Я использую библиотеку третьей стороны UserContext, который имеет только кучу {получить;}Фиктивные объекты без сеттера

public static UserContext Current { get; } 
public UserContact CurrentContact { get; } 
public string UserContactName { get; } 

В моем коде это просто возвращение CurrentUser как так:

void DoSomething(){ 
    UserContext Current = UserContext.Current; // 3rd party lib 
} 

У меня нет способа установить новый поддельный объект для модульного тестирования. Таким образом, для того, чтобы посмеяться над этим в моем коде я сделал следующее:

создал подкласс, который наследует от UserContext и перезаписать Текущее свойство:

public class UserContextFake : UserContext 
{ 
    public new UserContext Current { get; set; } 
} 

Затем созданный интерфейс и обертку:

public class UserContextWrapper : IUserContext 
{ 
    public UserContextWrapper() 
    { 
     userContext = UserContext.Current; 
    } 

    public UserContextWrapper(UserContext context) 
    { 
     userContext = context; 
    } 

    private readonly UserContext userContext; 

    public UserContext Current 
    { 
     get { return userContext; } 
    } 
} 

Теперь я могу вставлять userContextWrapper в свои классы. Я раскрываю два конструктора: тот, который использует материал сеанса UserContext.Current (сторонняя библиотека) для производственного кода и конструктор, который может получать пользовательский UserContextFake. В IoC я отображение IUserContext в UserContext

Вопрос: Как издеваются CurrentContact, если это не в интерфейсе, а свойство UserContext (UserContext.CurrentContact)

+0

Что значит правильно? Работает ли это для вас? –

+0

Является ли этот IUserContext реализованным сторонней библиотекой? –

+0

это не так. Вот почему мне пришлось создать оболочку, а затем изменить код в классе, который вызывал UserContext.Current, для ввода IUserContext. И в параметре wrapper less конструктор просто установит private userContext в материал сеанса из стороннего lib – ShaneKm

ответ

2

не могли бы вы просто создать интерфейс для всей партийной библиотеки 3dr? Затем реализуйте этот интерфейс и используйте этот класс в качестве обертки для сторонней библиотеки lib. методы. В тестируемом классе добавьте, например, свойство, которое может быть использовано для ввода макета интерфейса. Пример (непроверенный). HTH

public interface IThirdPartyLibraryWrapper 
{ 
    UserContext Current { get; } 
    UserContact CurrentContact { get; } 
    string UserContactName { get; } 
} 

public class ThirdPartyLibraryWrapper 
    : IThirdPartyLibraryWrapper 
{ 
    public UserContext Current 
    { 
     get { /* return Current from third party library */} 
    } 

    public UserContact CurrentContact 
    { 
     get{ /* return CurrentContact from third party library */} 
    } 

    public string UserContactName 
    { 
     get{ /* return UserContactName from third party library */} 
    } 
} 

public class ClassUnderTest 
{ 
    // Inject 3rd party lib 
    private IThirdPartyLibraryWrapper _library; 
    public virtual IThirdPartyLibraryWrapper Library 
    { 
     get 
     { 
      if (_library == null) 
       _library = new ThirdPartyLibraryWrapper(); 
      return _library; 
     } 
     set 
     { 
      if (value != null) 
       _library = value; 
     } 
    } 

    void DoSomething(){ 
     UserContext Current = Library.Current; 
    } 
} 

[TestMethod] 
public void DoSomething_WhenCalled_UsesLibraryMock() 
{ 
    // Arrange 
    UserContext fakeUserContext = new UserContext(); 
    Mock<IThirdPartyLibraryWrapper> libraryMock = new Mock<IThirdPartyLibraryWrapper>(); 
    libraryMock.Setup(l => l.Current).Returns(fakeUserContext); 
    ClassUnderTest cut = new ClassUnderTest(); 
    cut.Library = libraryMock.Object; 

    // Act 
    cut.DoSomething() 

    // Assert 
    // ... 
} 
+0

это имеет смысл. спасибо – ShaneKm

+0

Добро пожаловать! – dee

Смежные вопросы