Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should you Unit Test simple properties?

Should you Unit Test simple properties of a class, asserting that a value is set and retrieved? Or is that really just unit testing the language?

Example

public string ConnectionString { get; set; } 

Test

public void TestConnectionString() {     var c = new MyClass();     c.ConnectionString = "value";      Assert.Equal(c.ConnectionString, "value"); } 

I guess I don't see the value in that.

like image 612
Sam Avatar asked Sep 23 '13 19:09

Sam


1 Answers

I would suggest that you absolutely should.

  • What is an auto-property today may end up having a backing field put against it tomorrow, and not by you...

  • The argument that "you're just testing the compiler or the framework" is a bit of a strawman imho; what you're doing when you test an auto-property is, from the perspective of the caller, testing the public "interface" of your class. The caller has no idea if this is an auto property with a framework-generated backing store, or if there is a million lines of complex code in the getter/setter. Therefore the caller is testing the contract implied by the property - that if you put X into the box, you can get X back later on.

  • Therefore it behooves us to include a test since we are testing the behaviour of our own code and not the behaviour of the compiler.

  • A test like this takes maybe a minute to write, so it's not exactly burdensome; and you can easily enough create a T4 template that will auto-generate these tests for you with a bit of reflection. I'm actually working on such a tool at the moment to save our team some drudgery

  • If you're doing pure TDD then it forces you to stop for a moment and consider if having an auto public property is even the best thing to do (hint: it's often not!)

  • Wouldn't you rather have an up-front regression test so that when the FNG does something like this:


//24-SEP-2013::FNG - put backing field for ConnectionString as we're now doing constructor injection of it public string ConnectionString {    {get { return _connectionString; } }    {set {_connectionString="foo"; } }//FNG: I'll change this later on, I'm in a hurry }  ///snip  public MyDBClass(string connectionString) {    ConnectionString=connectionString; } 

You instantly know that they broke something?

If the above seems contrived for a simple string property I have personally seen a situation where an auto-property was refactored by someone who thought they were being oh so clever and wanted to change it from an instance member to a wrapper around a static class member (representing a database connection as it happens, the resons for the change are not important).

Of course that same very clever person completely forgot to tell anyone else that they needed to call a magic function to initialise this static member.

This caused the application to compile and ship to a customer whereupon it promptly failed. Not a huge deal, but it cost several hours of support's time==money.... That muppet was me, by the way!

EDIT: as per various conversations on this thread, I wanted to point out that a test for a read-write property is ridiculously simple:

[TestMethod] public void PropertyFoo_StoresCorrectly() {    var sut = new MyClass();    sut.Foo = "hello";    Assert.AreEqual("hello", sut.Foo, "Oops..."); } 

edit: And you can even do it in one line as per Mark Seeman's Autofixture

I would submit that if you find you have such a large number of public properties as to make writing 3 lines like the above a chore for each one, then you should be questioning your design; If you rely on another test to indicate a problem with this property then either

  • The test is actually testing this property, or
  • You will spend more time verifying that this other test is failing because the property is incorrect (via debugger, etc) than you would have spent typing in the above code
  • If some other test allows you to instantly tell that the property is at fault, it's not a unit test!

edit (again!): As pointed out in the comments, and rightly so, things like generated DTO models and the like are probably exceptions to the above because they are just dumb old buckets for shifting data somewhere else, plus since a tool created them, it's generally pointless to test them.

/EDIT

Ultimately "It depends" is probably the real answer, with the caveat that the best "default" disposition to be the "always do it" approach, with exceptions to that taken on an informed, case by case basis.

like image 179
Stephen Byrne Avatar answered Sep 21 '22 13:09

Stephen Byrne