Why can’t my test access a public constructor?

It’s late in the afternoon. Almost time to go home. Just one issue to finish. A simple class that needs a couple of simple tests. Should be a breeze.

Five minutes later you are ready to bang your head against your desk. The error messages keep flying. And you can’t see why.

If only you could fix this stupid “‘ActualProject.LateAfternoonMisery’ is inaccessible due to its protection level” error, then you’d be home free. Literally.

The class:

namespace ActualProject
{
    class LateAfternoonMisery
    {
        private int _MyInteger;

        public int AwesomeProperty { get {return _MyInteger; } }

        public LateAfternoonMisery()
        {
            _MyInteger = 42;
        }
    }
}

The test:

namespace TestProject
{
    [TestClass]
    public class LateAfternoonMisery_Tests
    {
        [TestMethod]
        public void LateAfternoonMisery_WhenConstructed_AwesomeProperty_ShouldReturn_DefaultValue()
        {
            var myLateAfternoonMisery = new LateAfternoonMisery();
            Assert.AreEqual(myLateAfternoonMisery.AwesomeProperty, 42);
        }
    }
}

Classes don’t get any simpler!
It should just work!
It is as if your Visual Studio and NUnit are plotting against you.

Stop fretting.
You still get to go home early.

There are three easy fixes to this situation.

Classes in C# are by default internal, not public. Which means that they are not visible outside the assembly in which they are used.

So, to fix the error, you can:

1. Add the production unit to your test project

You could add the LateAfternoonMisery.cs file to your test project, but…
I would strongly recommend against that. In Visual Studio it feels like a bad practice to use files outside of the project folder tree. But quite apart from esthetics, you would have to do it for every .cs file you would want to test. And there are much easier ways of getting your hands on your LateAfternoonMisery class and any other classes you want to test. Just read on.

2. Declare the class public instead of internal

    public class LateAfternoonMisery

While that is painless and Visual Studio usually adds the public accessibility when you add .cs files using any of the wizards, I still would recommend against that. The only classes that should be marked public in any assembly are the ones that provide the public interface of that assembly. All other classes should remain an internal implementation detail of that assembly. If only because if another assembly can use these classes, eventually one will and then you are stuck keeping it public or have to make a breaking change.

So what would I recommend? That’s number three:

3. Use the InternalsVisibleTo attribute on the ActualProject assembly

With the InternalsVisibleTo assembly attribute, the .NET framework provides a very neat way of opening up classes for test while keeping them internal to their assembly.

MSDN:

The attribute is applied at the assembly level. This means that it can be included at the beginning of a source code file, or it can be included in the AssemblyInfo file in a Visual Studio project.

I prefer to go the AssemblyInfo file route. You can find the AssemblyInfo.cs file under the properties entry in your project.

Assembly info file in your project

Adding the line below will act as Ibuprofen to your “inaccessible due to its protection level” error headache.

// Friends
[assembly: InternalsVisibleTo("TestProject")]

Enjoy!

Posted in Unit Testing
Tags: , , , , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Show Buttons
Hide Buttons