Testing and Validating Library Updates in .NET Framework Products
Best-practice guidance for verifying DLL updates, NuGet package upgrades, and delivery mechanism changes in .NET Framework–based applications, with a focus on runtime loading, GAC behavior, and dependency risk mitigation
Overview
This wiki describes the scope, intent, and best-practice guidance for testing and validating library-related changes in a software product, including DLL updates, NuGet package upgrades, and merge module removals or conversions.
The scope of this wiki is verification and risk mitigation, not implementation. It focuses on helping engineers and testers:
- Understand what needs to be validated when a library delivery mechanism changes
- Identify common failure patterns related to installation paths, dependency resolution, GAC loading, and lazy loading
- Design appropriate test environments (clean machines, upgrade scenarios, etc.)
- Define effective test coverage so that library changes do not introduce hidden runtime, installation, or performance issues
This wiki may help you:
- Avoid issues where incorrect DLL versions are loaded at runtime
- Detect missing or incorrectly declared NuGet dependencies
- Prevent GAC-related conflicts caused by identical assembly versions
- Ensure compliance requirements (signing, metadata, installation layout) are met
- Improve confidence that functional behavior remains consistent after library updates
This document serves as a reference of considerations and lessons learned, especially for scenarios that are easy to miss during routine testing but can lead to hard-to-diagnose production issues.
General Steps
Prepare the Test Environment
There are multiple test environment options—regular machine, clean machine, and machine with a previous version installed. Choose the appropriate environment based on the update type and risk level.
-
Regular Machine
- Use this when the update does not involve merge module removal or conversion and the related DLLs have always been direct references or NuGet packages.
- Or when you have assessed that previously delivered merge modules will not affect the current upgrade.
-
Clean Machine
-
Required when converting a merge module to a NuGet package or to a direct DLL reference.
A clean environment helps detect missing DLLs. If a DLL is missing from the installation folder but exists in the GAC with the same assembly version, the issue may be hidden and not surface as an error.
-
This prevents older GAC-installed versions from masking missing files or undeclared package dependencies.
-
-
(Optional) Machine with Previous Version Installed
-
Useful for validating upgrade behaviors, especially when libraries were previously delivered via merge modules.
-
Helps diagnose scenarios where multiple file versions share the same assembly version.
Using a baseline snapshot with a full installation of an earlier version helps validate unexpected DLL load paths and assess risks caused by residual files.
-
Confirm Expectations
1. Determine the Expected Library Information
-
Confirm the expected DLLs
- For merge modules, inspect contents using an MSI inspection tool.
- For NuGet packages, inspect package contents using the IDE.
-
Confirm the expected DLL file versions
-
Confirm the expected installation paths
There’s a bug related to DLLs being placed in an incorrect installation location after replacing a merge module with a NuGet package, causing runtime load failures.
-
Confirm whether code signing is required
There’s a bug related to third-party libraries being mistakenly signed with a product-specific key, and another where required digital signatures were missing.
-
Confirm whether copyright metadata is required
There’s a bug related to delivered libraries missing required copyright information due to build or packaging omissions.
2. (For Package Upgrades) Confirm Package Expectations
-
Confirm the expected package version
-
Confirm declared package dependencies
Missing or incorrectly declared dependencies may not surface on developer machines.
Testing on a clean machine is strongly recommended.There’s a bug related to a package that failed to declare dependencies correctly. Due to lazy loading, the issue was masked until tested on a clean environment.
3. (For Merge Module Removal or Conversion) Confirm Impacted DLL Behavior
-
Determine whether loading libraries from the GAC is allowed
There’s a bug related to the runtime loading a DLL from the GAC instead of the installation folder because both versions shared the same assembly version but had different code.
-
Confirm the expected assembly versions of the new DLLs
Determine the Test Scope and Test Programs
-
Account for lazy-loading behavior
- Some applications do not load all DLLs at startup.
There’s a bug related to a missed executable that was not covered during testing, causing issues to go unnoticed because the executable was only used in specific workflows.
- Recommended steps:
- Search the installation folder for all
.exefiles. - Identify what each executable does, when it is used, and what functionality it supports.
- Search the installation folder for all
-
Check for leftover old-version DLLs
- Scan the installation folder for pre-upgrade files.
There’s a bug related to older version DLLs remaining after an upgrade, causing the application to continue loading outdated assemblies.
-
Cover all usage locations of the upgraded library
There’s a bug related to removing a merge module where only one functional area was tested, while other dependent workflows were missed.
Determine the Expected Behavior of Test Functions
-
Existing functionality should behave the same before and after the update.
-
If the upgraded library introduces new features, create separate test coverage for them.
There’s a bug related to a UI component upgrade that introduced new capabilities. Original functionality still required full regression testing, while new features needed focused validation.
Start Testing Against Expectations
1. Check Files in the Installation Folder
-
(Optional) Inspect source code
- Use global search to identify overlooked project file references.
-
Verify installation locations
- Watch for libraries overwritten between projects in the same solution.
There’s a bug related to a library from a test project overwriting a product library, causing version confusion.
-
Verify versions, digital signatures, and metadata
2. Verify Runtime-Loaded Libraries
-
Recommended tools:
- Assembly binding log viewers
- Process inspection tools
-
For lazy-loaded applications
- Trigger all relevant functionality: menus, dialogs, editors, background services, and optional modules.
-
For one-time-load applications
- Ensure all windows appear and all executables in the installation directory can be launched.
There’s a bug related to focusing only on the main process and missing issues in secondary executables.
-
Verify runtime DLL load paths match expectations.
-
If the library was previously delivered via a merge module:
- Verify assembly versions.
- Confirm load locations.
- If loaded from the GAC:
- Compare file versions.
- Check for code differences.
- Temporarily remove the GAC copy to confirm correct loading behavior.
3. Functional Testing
-
Cover all functional branches that rely on the updated libraries.
-
Compare actual behavior with expected behavior.
There’s a bug related to improper error handling where a denied-access scenario caused an unhandled exception instead of a user-friendly message.
-
Pay attention to performance:
- Compare responsiveness against previous versions.
- Determine whether observed lag is reasonable.
There’s a bug related to a noticeable performance regression introduced after a library update.
Conclusion
This document provides guidance rather than a rigid checklist.
Apply the steps selectively based on update type, risk level, and product behavior.
The objective is to ensure library changes do not introduce unexpected runtime, installation, dependency, or performance issues that are difficult to detect later.
Useful Command Lines & Information
-
Get DLL assembly version:
[System.Reflection.AssemblyName]::GetAssemblyName("\\\\Path\\\\To\\\\Your.dll").Version -
GAC Path:
C:\\Windows\\Microsoft.NET\\assembly -
Check whether an assembly exists in the GAC:
gacutil /l | findstr Your.Assembly.Name -
Install a .NET assembly into the GAC:
gacutil /i Your.Assembly.dll -
Remove an assembly from the GAC:
gacutil /u Your.Assembly.Name