PostSharp 4.3 / / Post­Sharp Documentation / Custom Patterns / Testing and Debugging Aspects / Writing Simple Tests
Writing Simple Tests

When designing a test strategy for aspects, it is fundamental to understand that aspects cannot be used in isolation. They are always used in the context of the code artefact to which it has been applied. Therefore, when writing an aspect, two kinds of test artifacts must be written:

  • Test target code to which the aspect will be applied.

  • Test invocation code that invokes the target code and verifies that the combination of the aspect and the target code exhibits the intended behavior.

Achieving large test coverage

As with other code, you have to test the aspect with input context that varies enough to produce a large code coverage.

In the case of aspects, the input context is composed of the following items:

  • Arguments of the aspect itself, i.e. constructor arguments and property values. If the aspect behavior depends of aspect arguments, high code coverage of the aspect requires varying aspect arguments.

  • Target code can be considered as conceptually being a part of the input arguments of the aspect. For instance, if an aspect contains logic that depends on the method being static or non-static, you should test the aspect against both static and non-static methods.

  • Arguments of the target code can affect the run-time behavior of the aspect. For instance, a buggy aspects may incorrectly handle null arguments.

Example: testing a caching aspect

The following example demonstrates how to test a caching aspect. High code coverage is achieved by varying the target code and testing with null and non-null parameters.

C#
using
                         System;
                        

                        using
                         Microsoft.VisualStudio.TestTools.UnitTesting;
                        


                        namespace
                         Samples
{
    [TestClass]
    
                        public
                         
                        class
                         TestCacheAspect
    {
        
                        private
                         
                        static
                         
                        int
                         invocations;

        
                        // Instance method without parameters
                        

                        
        [TestMethod]
        
                        public
                         
                        void
                         TestInstanceMethodWithoutParameter()
        {
            
                        int
                         call1 = 
                        this
                        .InstanceMethodWithoutParameter();
            
                        int
                         call2 = 
                        this
                        .InstanceMethodWithoutParameter();

            Assert.AreEqual(call1, call2);
        }

        [Cache]
        
                        private
                         
                        int
                         InstanceMethodWithoutParameter()
        {
            
                        return
                         invocations++;
        }

        
                        // Static method without parameters
                        

                        
        [TestMethod]
        
                        public
                         
                        void
                         TestStaticMethodWithoutParameter()
        {
            
                        int
                         call1 = StaticMethodWithoutParameter();
            
                        int
                         call2 = StaticMethodWithoutParameter();

            Assert.AreEqual(call1, call2);
        }

        [Cache]
        
                        private
                         
                        static
                         
                        int
                         StaticMethodWithoutParameter()
        {
            
                        return
                         invocations++;
        }

        
                        //  Instance method with parameters
                        

                        
        [TestMethod]
        
                        public
                         
                        void
                         TestInstanceMethodWithParameter()
        {
            
                        int
                         call1a = 
                        this
                        .InstanceMethodWithParameter(
                        "foo"
                        );
            
                        int
                         call2a = 
                        this
                        .InstanceMethodWithParameter(
                        null
                        );
            
                        int
                         call1b = 
                        this
                        .InstanceMethodWithParameter(
                        "foo"
                        );
            
                        int
                         call2b = 
                        this
                        .InstanceMethodWithParameter(
                        null
                        );

            Assert.AreEqual(call1a, call1b);
            Assert.AreEqual(call2a, call2b);
            Assert.AreNotEqual(call1a, call2a);
        }

        [Cache]
        
                        private
                         
                        int
                         InstanceMethodWithParameter(
                        string
                         param)
        {
            
                        return
                         invocations++;
        }
    }
}