Reputation: 33143
UPDATE: I've changed the wording of the question. Previously it was a yes/no question about if a base class could be changed at runtime.
I may be working on mission impossible here, but I seem to be getting close. I want to extend a ASP.NET control, and I want my code to be unit testable. Also, I'd like to be able to fake behaviors of a real Label (namely things like ID generation, etc), which a real Label can't do in an nUnit host.
Here a working example that makes assertions on something that depends on a real base class and something that doesn't-- in a more realistic unit test, the test would depend on both --i.e. an ID existing and some custom behavior.
Anyhow the code says it better than I can:
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();
}
}
Upvotes: 2
Views: 1312
Reputation: 15722
I do not understand your example quite well. But if you want to partially change the behavior of your LabelWrapper
for unit tests, you could use Moq.
Moq is a Mocking framework which allows to setup your Mock with specific behavior on selected methods. This would mean you would test a mocked version of your LabelWrapper
which is quite unconventional, however.
Upvotes: -1
Reputation: 754725
This is simply not possible in .Net. You cannot alter compiled meta-data on the fly.
Think of all of the havoc this would cause. Pretend I had the following situation
class Example {
Label l = new LabelWrapper();
}
This code has executed and suddenly your code runs that switches the base type of LabelWrapper
to be FakeLabel
. This raises a number of very hairy problems, including but not limited to
Example
?Example
as this code is now completely invalid? Upvotes: 3