C#
InternalsVisibleTo
debugging
assembly
.NET

InternalsVisibleTo attribute isn't working

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

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:

csharp
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("MyLibrary.Tests")]

Now an internal type inside MyLibrary can be used from the MyLibrary.Tests assembly:

csharp
1namespace MyLibrary;
2
3internal static class TokenParser
4{
5    internal static int CountSegments(string value) => value.Split('.').Length;
6}
csharp
1using MyLibrary;
2using Xunit;
3
4public class TokenParserTests
5{
6    [Fact]
7    public void CountSegments_ReturnsExpectedValue()
8    {
9        Assert.Equal(3, TokenParser.CountSegments("a.b.c"));
10    }
11}

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.

xml
1<Project Sdk="Microsoft.NET.Sdk">
2  <PropertyGroup>
3    <TargetFramework>net8.0</TargetFramework>
4    <AssemblyName>MyLibrary.Tests</AssemblyName>
5  </PropertyGroup>
6</Project>

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 private members
  • 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.

bash
dotnet clean
dotnet build
dotnet test

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 internal code.
  • Forgetting the public key when strong naming is enabled.
  • Expecting private members to become visible. The attribute only affects internal.
  • Diagnosing the wrong failure. A missing project reference and an accessibility issue can look similar at first glance.

Summary

  • 'InternalsVisibleTo must be compiled into the assembly that contains the internal members.'
  • 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 internal members, not private ones.
  • A clean rebuild and a minimal test case are the fastest ways to separate assembly identity problems from ordinary reference issues.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track 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.

Browse interview questions

All Rights Reserved.