简体   繁体   中英

Why does a generic test fail but the non generic does not?

I have a bunch of exceptions which follow the same schema: I have a parameter that is given into a text like this:

public class ContainerCouldNotStartedException : Exception
{
    private static readonly string Text = "Container could not be started: {0}. Please see docker logging for more information";

    public ContainerCouldNotStartedException()
    {
    
    }
    
    public ContainerCouldNotStartedException(string name)
        : base(String.Format(Text, name))
    {

    }
}

Now I want to test this.

To avoid 10 copied test for 10 exceptions my idea is to test it generic like this:

public static void Test_String_Is_In_Message(Type type, string name)
{
    ConstructorInfo ctor = type.GetConstructor(new[] { typeof(string) });
    dynamic exception = ctor.Invoke(new object[] { name });
    Assert.That(exception.Message, Does.Contain(name));
}

And call it like this:

[Test]
[TestCase("HarryPotter")]
[TestCase("HermineGranger")]
[TestCase("LuciusMalfoy")]
public void Message_Has_Name(string name)
{
    ExceptionTest.Test_String_Is_In_Message(typeof(ContainerCouldNotStartedException), name);
    ExceptionTest.Test_String_Is_In_Message(typeof(DatabaseNameNotCorrectException), name);
    ExceptionTest.Test_String_Is_In_Message(typeof(DatabaseNotCorrectException), name);
    ExceptionTest.Test_String_Is_In_Message(typeof(DatabaseVersionNotReadableException), name);
    ExceptionTest.Test_String_Is_In_Message(typeof(VersionNotFoundException), name);
}

That works very fine and all tests are green.

Now one single exception has a GUID parameter, instead of a string.

So instead of having my method Test_String_Is_In_Message copied to times, I made it generic:

public static void Test_String_Is_In_Message<T>(Type type, T name)
{
    ConstructorInfo ctor = type.GetConstructor(new[] { typeof(T) });
    dynamic exception = ctor.Invoke(new object[] { name });
    Assert.That(exception.Message, Does.Contain(name));
}

Now all tests fail.

When I debug the test it is all fine for me, I can see the name in the message, but the assert still fails. Why?

The usage of dynamic kind of obfuscated the problem. The problem is that Does.Contain() expects a string according to the docs . So changing your helper method to the following made all the tests pass for me:

public static void Test_String_Is_In_Message<T>(Type type, T name)
{
    ConstructorInfo ctor = type.GetConstructor(new[] { typeof(T) });
    try
    {
        ctor.Invoke(new object[] { name });
    }
    catch (Exception e)
    {
        Assert.That(e.Message, Does.Contain(name.ToString()));
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM