Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this possible in C#?

Tags:

c#

reflection

I have an extension method for testing so I can do this:

var steve = new Zombie();
steve.Mood.ShouldBe("I'm hungry for brains!");

The extension method:

public static void ShouldBe<T>(this T actual, T expected)
{
    Assert.That(actual, Is.EqualTo(expected));
}

This shows:

Expected: "I'm hungry for brains!"
But was:  "I want to shuffle aimlessly"

Is there any hack I can pull off to get the name of the property "BrainsConsumed" from within my extension method? Bonus points would be the instance variable and type Zombie.

UPDATE:

The new ShouldBe:

public static void ShouldBe<T>(this T actual, T expected)
{
    var frame = new StackTrace(true).GetFrame(1);
    var fileName = frame.GetFileName();
    var lineNumber = frame.GetFileLineNumber() - 1;
    var code = File.ReadAllLines(fileName)
        .ElementAt(lineNumber)
        .Trim().TrimEnd(';');

    var codeMessage = new Regex(@"(^.*)(\.\s*ShouldBe\s*\()([^\)]+)\)").Replace(code, @"$1 should be $3");

    var actualMessage = actual.ToString();
    if (actual is string)
        actualMessage = "\"" + actual + "\"";

    var message = string.Format(@"{0} but was {1}", codeMessage, actualMessage);

    Assert.That(actual, Is.EqualTo(expected), message);
}

and this prints out:

steve.Mood should be "I'm hungry for brains!" but was "I want to shuffle aimlessly"

Thanks everyone, esp. Matt Dotson, this is awesome. BTW don't feed the silky trolls people.

like image 333
whatupdave Avatar asked Dec 07 '09 06:12

whatupdave


1 Answers

You can get the code if it's a debug build by using some of the diagnostics classes. Given that this is for unit tests, DEBUG is probably reasonable.

public static void ShouldBe<T>(this T actual, T expected)

{

var frame = new StackTrace(true).GetFrame(1);
var fileName = frame.GetFileName();
var lineNumber = frame.GetFileLineNumber() - 1;

string code = File.ReadLines(fileName).ElementAt(lineNumber).Trim();

Debug.Assert(actual.Equals(expected), code);

}

For your example, code = "steve.BrainsConsumed.ShouldBe(0);"

Obviously you should add some error checking to this code, and you could probably make it faster by not reading all the lines in the file.

like image 58
Matt Dotson Avatar answered Sep 24 '22 13:09

Matt Dotson