Unit testing C++ CLR

Günther Humer 1 Reputation point
2022-11-08T11:49:22.9+00:00

What is the best approach to write Unit Tests for C++/CLR?

We have a solution that includes C++ native, C++/CLR and C#.Net code.

When I try to add a C++/CLR reference to a C#.net Unit Test project, it compiles, but when I run the tests it says "Could not load file or assembly".
Copy-Local is true and it is in the same directory as the C# assambly under test.

.NET CLI
.NET CLI
A cross-platform toolchain for developing, building, running, and publishing .NET applications.
324 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,593 questions
Visual Studio Testing
Visual Studio Testing
Visual Studio: A family of Microsoft suites of integrated development tools for building applications for Windows, the web and mobile devices.Testing: The act or process of applying tests as a means of analysis or diagnosis.
334 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Tianyu Sun-MSFT 28,661 Reputation points Microsoft Vendor
    2022-11-08T13:34:08.417+00:00

    Hi @Günther Humer ,

    Welcome to Microsoft Q&A forum.

    Have you also tried to use Native Unit Test Project? And in this Native Unit Test project, see if property => Configuration Properties => Advanced => C++/CLI Properties options help.

    Best Regards,
    Tianyu

    • If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
      Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

  2. Günther Humer 1 Reputation point
    2022-12-13T16:41:03.227+00:00

    TLDR

    Custom AssemblyResolve in a C++/CLR-project, which has to be set up (SetUpAssemblyResolve()) before running the tests.
    It simply tries to load the Assembly from "./"

    using namespace System;  
    using namespace ::System::Reflection;  
    using namespace System::IO;  
      
    Assembly^ OnAssemblyResolve(System::Object^ obj, System::ResolveEventArgs^ args)  
    {  
    auto requestedName = gcnew AssemblyName(args->Name);  
      
      auto assemblyPath = Path::GetFullPath(Path::Combine("./", requestedName->Name + ".dll"));  
      if (!File::Exists(assemblyPath)) {  
        assemblyPath = Path::GetFullPath(Path::Combine("./", requestedName->Name + ".exe"));  
        if (!File::Exists(assemblyPath))  
          return nullptr;  
      }  
        
      auto assembly = Assembly::LoadFrom(assemblyPath);  
      return assembly;  
    }  
      
    void SetUpAssemblyResolve()  
    {  
    AppDomain::CurrentDomain->AssemblyResolve += gcnew System::ResolveEventHandler(&OnAssemblyResolve);  
    }  
    

    I created a test-project where you can see the problems. And I also found a solution.

    The TestProject can be found here:
    https://github.com/relascope/TestingCppClrCs/

    This Commit still has problems:
    https://github.com/relascope/TestingCppClrCs/commit/c943d806db2deba5470cbb49994371cbbf92331e

    Native C++ Tests calling Dll Calling C++/CLR calling C#-assembly fails to load the assembly.
    Setting the test project to compile with /clr does not help, the tests disappear. Anyway, this does not matter, since calling into C++/CLR-Dll is possible the same way like calling native code, and it doesn't really matter, if the test-code itself is native C++ or C++/CLR.

    /Diag:testdiagnostics.log
    shows, that the vstest.console.exe tries to load the assemblies only from some Visual Studio folders.
    "./" is not searched.

    Since we cannot mock away all C# calls (Solution is too big and has grown over the years and some Interfaces are in C#), it is essential to use it.

    One way would be to use google-test (which has no problem loading the C# assemblies), but here we are facing difficulties with Typemocks Isolator++.

    The Solution for now is to use AppDomain::CurrentDomain->AssemblyResolve to register a custom AssemblyResolver, which just tries to load from "./".
    For the testing spike, this solution is sufficient (can be seen in the latest commit of the TestingCppClrCs Project).

    The next step will be the integration into our real project.

    0 comments No comments