简体   繁体   中英

How to write a unit test for “T must be a reference type”?

Consider:

class MyClass<T> where T : class
{
}

In that case, the where clause is enforcing a specification that MyClass is only a generic of a reference type.

Ideally I should have a unit test that tests this specification. However, this unit test obviously won't work, but it explains what I'm trying to accomplish:

[Test]
[DoesNotCompile()]
public void T_must_be_a_reference_type()
{
    var test = new MyClass<int>();
}

What can I do to test a spec that's implemented by not allowing the code to compile?

EDIT :

More info: Ok, so my reasoning for doing this (haha) is that I've been following a TDD methodology, in which you can't write any code unless you have a failing unit test. Let's say you had this:

class MyClass<T> { }

What test can you write that would fail unless T were a class? Something like default(T) == null ?

Further EDIT :

So after a "root cause analysis" on this, the problem is that I was relying on default(T) being null in a consumer of this class, in an implicit way. I was able to refactor that consumer code into another class, and specify a generic type restriction there (restricting it to class ) which effectively makes that code not compile if someone were to remove the restriction on the class I'm talking about above.

Why would you need a unit test for this? Do you write a unit test for a method such as

public void Foo(string x)

to check that it can only take strings, and not integers? If not, what do you see as the difference?

EDIT: Just to be slightly less whimsical: in this case the spec is validated by the declaration . Tests should generally test behaviour . That's one of the things I like about Code Contracts: I don't feel any need to unit test the contracts unless they express something complicated - in which case it's that complexity that I'd be testing, not the "contracts are enforced" bit.

EDIT: To respond to the question edit:

What test can you write that would fail unless T were a class?

You could write something like:

Type definition = typeof(MyClass<>);
Assert.Throws<ArgumentException>(() => definition.MakeGenericType(typeof(int)));

However, that seems to be going against the real purpose of testing...

You shouldn't test whether the compiler does its work. If you specify this in code, this is enough. From a code perspective, this is roughly the same as this:

[Test]
public void Test_whether_add_works()
{
    int i = 1 + 2;

    Assert.AreEqual(3, i);
}

This is a great question! So much agree with your test driven approach. What you are struggling with is actually the clash of two paradigms. The old paradigm that programs should be proven correct using mathematics without running them (a legacy of our profession's ancestry in mathematics) and the new paradigm that programd should be proven correct by executing with example use cases, ie tests. So what you are about to try is to apply the practice of the new paradigm on an artifact of the old paradigm, which of course won't really work…

More on the dichotomy of types and tests, see this excellent article by Chris Smith, http://web.archive.org/web/20080822101209/http://www.pphsg.org/cdsmith/types.html

Are you writing a correct unit test? It looks like your a going to test C# compiler but not your code.

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