Create unit tests to ensure consistency

I developed an immutable class because I want to have value semantics for it. I wrote a tip in the class comments section

// "This class is immutable, don't change this when adding new features to it."

But I know, sometimes these comments are ignored by other team members, so I would like to create a unit test as an extra protection. Any idea how to do this? Is it possible to check a class through reflection to make sure that only constructors change its internal state?

(Using C # 2.0 and NUnit, if that matters to everyone).

+5
source share
4 answers

, FieldInfo.IsInitOnly .

, , string, , , , - , .

, readonly . , .

using System;
using System.Linq;
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ImmutableTests
{
    [TestClass]
    public class AssertImmutableTests
    {
        [TestMethod]
        public void Is_int_immutable()
        {
            Assert.IsTrue(Immutable<int>());
        }

        [TestMethod]
        public void Is_string_immutable()
        {
            Assert.IsTrue(Immutable<string>());
        }

        [TestMethod]
        public void Is_custom_immutable()
        {
            Assert.IsTrue(Immutable<MyImmutableClass>());
        }

        [TestMethod]
        public void Is_custom_mutable()
        {
            Assert.IsFalse(Immutable<MyMutableClass>());
        }

        [TestMethod]
        public void Is_custom_deep_mutable()
        {
            Assert.IsFalse(Immutable<MyDeepMutableClass>());
        }

        [TestMethod]
        public void Is_custom_deep_immutable()
        {
            Assert.IsTrue(Immutable<MyDeepImmutableClass>());
        }

        [TestMethod]
        public void Is_propertied_class_mutable()
        {
            Assert.IsFalse(Immutable<MyMutableClassWithProperty>());
        }

        private static bool Immutable<T>()
        {
            return Immutable(typeof(T));
        }

        private static bool Immutable(Type type)
        {
            if (type.IsPrimitive) return true;
            if (type == typeof(string)) return true;
            var fieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            var isShallowImmutable = fieldInfos.All(f => f.IsInitOnly);
            if (!isShallowImmutable) return false;
            var isDeepImmutable = fieldInfos.All(f => Immutable(f.FieldType));
            return isDeepImmutable;
        }
    }

    public class MyMutableClass
    {
        private string _field;
    }

    public class MyImmutableClass
    {
        private readonly string _field;
    }

    public class MyDeepMutableClass
    {
        private readonly MyMutableClass _field;
    }

    public class MyDeepImmutableClass
    {
        private readonly MyImmutableClass _field;
    }

    public class MyMutableClassWithProperty
    {
        public string Prop { get; set; }
    }
}
+8

, , , ( FieldInfo.IsInitOnly).

, - - List<int>, .

+7

. , , .

, #

+3

, NDepend, "" , .

- . , IImmutable, NDepend , - , , :

WARN IF Count > 0 IN SELECT TYPES WHERE 
  Implement "MyCompany.MyAssemblies.Dto.IImmutable" AND
  !IsImmutable

, .

Obviously, this is actually not a unit test. However, it can be integrated as part of your assembly, and you cannot build it in the same way as unit test, so I thought I mentioned it!

See here for more information on what he actually does and how.

+2
source

All Articles