Unittest of Postsharp aspect fails, when calling GetSemanticInfo

bernd.stoetzel's Avatar

bernd.stoetzel

23 Mar, 2018 01:02 PM

Hi,

we have a type level aspect for tracing like this:
    [ProvideAspectRole( StandardRoles.Tracing )]
    [AspectRoleDependency( AspectDependencyAction.Order, AspectDependencyPosition.After, StandardRoles.Threading )]
    [Serializable]
    [MulticastAttributeUsage( MulticastTargets.Class )]
    public sealed class TracingAttribute : TypeLevelAspect
    {
     .......
        public IEnumerable<MethodBase> SelectCodeElements( Type targetType )
        {
            const BindingFlags bindingFlags =
                    BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic;
            IEnumerable<MethodBase> constructors = targetType.GetConstructors( bindingFlags );
            IEnumerable<MethodBase> methods = targetType.GetMethods( bindingFlags ).Where( m => !m.IsAbstract && m.GetSemanticInfo().IsSelectable);
            IEnumerable<MethodBase> tracedMembers = methods.Union( constructors ).Where( HasToBeTraced );
            return tracedMembers;
        }
}

We had to add the check m.GetSemanticInfo().IsSelectable after upgrading to PostSharp V5 to exclude anonymous methods from aspect selection.
We have a unittest for above method SelectCodeElements which does (amongst other things) this:

            TracingAttribute target = new TracingAttribute(Member.All, AccessModifier.All);
            Type type = Type.GetType("H.Common.Diagnostics.Tracing.Test.Unit.DisposeSample");

            //Act
            IEnumerable<MethodBase> filteredMembers = target.SelectCodeElements(type);

The call to SelectCodeElements now throws an exception:
System.InvalidOperationException : The project instance is not available. You are probably running build-time only code in run-time.

I understand that within the unittest environment we are not in build-time, so I understand why we get this exception (GetSemanticInfo is only usable during buildtime)

My question is: is there some possibility to setup the unittest in a way, such that the build-time environment is simulated? What is your suggestion on how to test the aspect implementation in this case?

Thanks,
Bernd

  1. Support Staff 1 Posted by PostSharp Techn... on 23 Mar, 2018 02:23 PM

    PostSharp Technologies's Avatar

    Hello Bernd,

    unit testing of build-time logic is documented at http://doc.postsharp.net/testing-build-time-logic.

    The link to the PostSharp.BuildTests.targets is broken at the moment. Please use the attached file instead.

    You'll also need to download MSBuild Community Tasks zip distribution from https://github.com/loresoft/msbuildtasks/releases and unzip it to the directory shown in an error message emitted after the first attempt to run a test.

    Does this work for you?

    Best regards,
    -tony

  2. 2 Posted by bernd.stoetzel on 23 Mar, 2018 03:00 PM

    bernd.stoetzel's Avatar

    Hello Tony,

    unfortunately this does not help in my case.

    The exception I get is
    System.InvalidOperationException : The project instance is not available. You are probably running build-time only code in run-time.
       at PostSharp.Extensibility.ServiceCache.get_Current()
       at PostSharp.Reflection.ReflectionHelper.GetSemanticInfo(MemberInfo member)

    So seemingly the PostSharpEnvironment.CurrentProject is null in this test case. The question is, if there is any possibility to set PostSharpEnvironment.CurrentProject in a unit test scenario?

    Best regards,
    Bernd

  3. Support Staff 3 Posted by PostSharp Techn... on 23 Mar, 2018 04:16 PM

    PostSharp Technologies's Avatar

    Hello Bernd,

    the idea behind this build-testing framework is, that for each test case, you create a .cs file with a Main method. The project then can't be neither compiled nor ran from Visual Studio, since each .cs file would contain a Main method, as described in the documentation.

    In each .cs file, you are going to use your aspect as if you'd use it in a production code. The test is considered failed either if the build fails or if the return code of the Main method is not 0.

    The tests are not executed using a unit test runner as regular run-time unit tests, but using MSBuild as described in the documentation. The required build environment is then real rather than mocked.

    I understand that you have already a set of unit tests and this GetSemanticInfo() extension method has broken them.

    Instead of migrating all these tests, you could wrap the GetSemanticInfo().IsSelectable expression using another method and skip the call when not running in build-time. For example:

    public static bool IsSelectable(this MemberInfo member)
    {
        return PostSharpEnvironment.IsPostSharpRunning ? member.GetSemanticInfo().IsSelectable : true;
    }
    

    You would then test only the cases with anonymous methods using the build-test framework if you'd want to.

    Is this viable?

    Best regards,
    -tony

  4. 4 Posted by bernd.stoetzel on 26 Mar, 2018 07:06 AM

    bernd.stoetzel's Avatar

    Hello Tony,

    thanks for the explanation. I understand that build time tests needs a different environment and actually we have already some tests using the description you gave to test build-time behavior.

    If there is no way to somehow set the PostSharpEnvironment programmatically, than that's the way it is. I will consider your suggestion of using a wrapper method, but probably I will just migrate the existing runtime tests (not too many of them fortunately).

    Thanks for you help.
    Bernd

  5. Support Staff 5 Posted by PostSharp Techn... on 26 Mar, 2018 07:34 AM

    PostSharp Technologies's Avatar

    Hello Bernd,

    the missing project instance mentioned in the exception message is just a tip of an iceberg. There's no way to make the GetSemanticInfo() extension method work in run-time.

    We are going to close this request as we believe it was solved. Please feel free to reopen the discussion if you need more help.

    Best regards,
    -tony

  6. PostSharp Technologies closed this discussion on 26 Mar, 2018 07:34 AM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac