InternalsVisibleTo attribute isn't working
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
InternalsVisibleTo is a C# assembly-level attribute that lets one assembly access internal types and members from another assembly. When it seems not to work, the underlying issue is usually not the attribute itself but a mismatch in assembly names, signing, or where the attribute was compiled.
The key point is that InternalsVisibleTo is very literal. It does not use namespaces, project folder names, or package names. It uses the compiled assembly identity.
Add the Attribute to the Assembly That Owns the Internals
The attribute must be compiled into the assembly that contains the internal members. In a library project, a simple AssemblyInfo.cs file is enough:
Now an internal type inside MyLibrary can be used from the MyLibrary.Tests assembly:
If that still fails, the first thing to check is the real assembly name of the test project.
Verify the Assembly Name, Not the Namespace
The attribute string must match the test assembly name exactly. If your .csproj overrides AssemblyName, that value wins.
A common failure pattern is:
- library namespace is
MyLibrary - test namespace is
MyLibrary.Tests - compiled assembly name is actually something else
In that case, [assembly: InternalsVisibleTo("MyLibrary.Tests")] looks right but still does not match the assembly that the compiler produced. Check the project file or the built DLL name instead of guessing.
Strong-Named Assemblies Need the Public Key
If the target assembly is strong-named, the simple assembly name is not enough. The friend declaration must include the full public key of the consuming assembly.
Conceptually, the declaration changes from:
- '
MyLibrary.Tests'
to:
- '
MyLibrary.Tests, PublicKey=...'
This is one of the most common reasons InternalsVisibleTo works in a quick example and then fails in a larger enterprise solution. Unsigned examples are simpler, but signed assemblies enforce a stricter identity.
Remember What the Attribute Does Not Change
InternalsVisibleTo only exposes internal members to the named friend assembly. It does not:
- expose
privatemembers - bypass accessibility rules for unrelated assemblies
- fix build-order or reference problems
- apply to the wrong target framework output automatically
That last point matters in multi-targeted solutions. If the attribute is conditionally compiled or only included for one target, the tests might pass for one build and fail for another.
A Minimal End-to-End Check
When debugging, reduce the setup to one internal member and one test. That helps isolate whether the problem is accessibility or something else such as stale build output.
If a clean rebuild fixes the issue, an older assembly may have been lingering in the output folder. If it does not, inspect the exact compiler error message. Messages about inaccessible members usually point to a friend assembly mismatch, while missing type errors point to a reference or namespace problem.
Common Pitfalls
- Using the project name or namespace instead of the compiled assembly name.
- Putting the attribute in the test project rather than in the library that owns the
internalcode. - Forgetting the public key when strong naming is enabled.
- Expecting
privatemembers to become visible. The attribute only affectsinternal. - Diagnosing the wrong failure. A missing project reference and an accessibility issue can look similar at first glance.
Summary
- '
InternalsVisibleTomust be compiled into the assembly that contains theinternalmembers.' - The attribute value must match the consuming assembly name exactly.
- Strong-named friend assemblies require the full public key, not just the short name.
- The attribute only exposes
internalmembers, notprivateones. - A clean rebuild and a minimal test case are the fastest ways to separate assembly identity problems from ordinary reference issues.
Related reading
- Intersection of multiple lists with IEnumerable.Intersect
- IntPtr, SafeHandle and HandleRef - Explained
- Invalid cast from ''System.Int32'' to ''System.Nullable1System.Int32, mscorlib
- Invalid postback or callback argument. Event validation is enabled using 'pages enableEventValidationtrue/
- Interpreting Tensorboard Distributions - Weights not Changing, only Biases
- Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why?
- Invalid token 'void' when compling async..await on build server
- InvalidOperationException Unable to resolve service for type 'Microsoft.AspNetCore.Http.IHttpContextAccessor

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.