2010-03-23 1 views
2

ОБНОВЛЕНИЕ: Я изменил формулировку вопроса. Раньше было да/нет вопроса о том, можно ли изменить базовый класс во время выполнения.Как мне подделать/подделать/заменить/заглушить базовый класс при единичном тестировании на C#?

Возможно, я работаю над выполнением миссии, но я, кажется, приближаюсь. Я хочу расширить элемент управления ASP.NET, и я хочу, чтобы мой код был единым проверяемым. Кроме того, я хотел бы иметь возможность подделывать поведение реальной метки (а именно такие вещи, как генерация идентификаторов и т. Д.), Которые настоящий ярлык не может сделать на узле nUnit.

Здесь рабочий пример, который делает утверждения о чем-то, что зависит от реального базового класса и чего-то, чего нет ... в более реалистичном модульном тесте, испытание будет зависеть от обоих --i.e. существующий идентификатор и некоторое пользовательское поведение.

Во всяком случае код говорит, что это лучше, чем я могу:

public class LabelWrapper : Label //Runtime 
//public class LabelWrapper : FakeLabel //Unit Test time 
{ 
    private readonly LabelLogic logic= new LabelLogic(); 

    public override string Text 
    { 
     get 
     { 
      return logic.ProcessGetText(base.Text); 
     } 
     set 
     { 
      base.Text=logic.ProcessSetText(value); 
     } 
    } 
} 

//Ugh, now I have to test FakeLabelWrapper 
public class FakeLabelWrapper : FakeLabel //Unit Test time 
{ 
    private readonly LabelLogic logic= new LabelLogic(); 

    public override string Text 
    { 
     get 
     { 
      return logic.ProcessGetText(base.Text); 
     } 
     set 
     { 
      base.Text=logic.ProcessSetText(value); 
     } 
    } 
} 

[TestFixture] 
public class UnitTest 
{ 
    [Test] 
    public void Test() 
    { 
     //Wish this was LabelWrapper label = new LabelWrapper(new FakeBase()) 
     LabelWrapper label = new LabelWrapper(); 
     //FakeLabelWrapper label = new FakeLabelWrapper(); 
     label.Text = "ToUpper"; 
     Assert.AreEqual("TOUPPER",label.Text); 
     StringWriter stringWriter = new StringWriter(); 
     HtmlTextWriter writer = new HtmlTextWriter(stringWriter); 
     label.RenderControl(writer); 
     Assert.AreEqual(1,label.ID); 
     Assert.AreEqual("<span>TOUPPER</span>", stringWriter.ToString()); 
    } 
} 

public class FakeLabel 
{ 
    virtual public string Text { get; set; } 
    public void RenderControl(TextWriter writer) 
    { 
     writer.Write("<span>" + Text + "</span>"); 
    } 
} 

//System Under Test 
internal class LabelLogic 
{ 
    internal string ProcessGetText(string value) 
    { 
     return value.ToUpper(); 
    } 

    internal string ProcessSetText(string value) 
    { 
     return value.ToUpper(); 
    } 
} 

ответ

3

Это просто невозможно в .Net. Вы не можете изменять скомпилированные метаданные «на лету».

Подумайте обо всех хаосах, которые это вызовет. Притворись я имел следующую ситуацию

class Example { 
    Label l = new LabelWrapper(); 
} 

Этот код выполняется, и вдруг ваш код работает, который переключает базовый тип LabelWrapper быть FakeLabel. Это вызывает ряд очень волосатых проблем, включая, но не ограничиваясь ими,

  • Что произойдет с существующими экземплярами Example?
  • Что произойдет с новыми экземплярами Example, так как этот код полностью недействителен?
  • Количество кошмаров в области безопасности, которое вводит в действие, поскольку теперь я могу мутировать свой объект на лету так, чтобы API-интерфейсы не учитывали.
+0

Я согласен с вами в том, что во время выполнения не существует способа изменить базовый класс. Я все еще надеюсь найти образец, чтобы имитировать его. Но я не уверен (если это было возможно), как это отличается от фабрики, которая возвращает альтернативные реализации, которые имеют один и тот же базовый класс или поддерживают один и тот же интерфейс. Завод может выбрать вредоносную реализацию или недействительную реализацию. – MatthewMartin

-1

Я не очень хорошо понимаю ваш пример. Но если вы хотите частично изменить поведение вашего LabelWrapper для модульных испытаний, вы можете использовать Moq.

Moq - это система Mocking, которая позволяет настроить ваш Mock с определенным поведением по выбранным методам. Это означало бы, что вы проверили бы издеваемую версию вашего LabelWrapper, которая является довольно нетрадиционной.

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