Troubleshooting assembly dependency chain issues on TeamCity - c#

We have a .NET solution that I'm trying to get to run in our new CI environment, TeamCity.
The solution builds and runs, and all unit tests run (not all pass, but that's a different story) on our dev machines.
It builds properly on the CI server as well, but when running the MSTest configuration, it fails, giving a message like:
Unable to load the test container '[one of my test assemblies]' or one of its dependencies. Error details: System.IO.FileNotFoundException: Could not load file or assembly '[one of my assemblies]' or one of its dependencies. The system cannot find the file specified.
Well, my assembly is built and available, so that's unlikely. On my local dev machine, I can get more detail with procmon or the like to see where the dependency chain is broken, but I'm not sure how I can do that against a remote server.
How can I find out what my CI server is missing to do its job? Is there some logging I can enable or something?

Sounds like the working directory is wrong when you are attempting to run tests.
Is your Build and Unit Tests steps in the same "Build Configuration"?

Related

Unit test passes when running the test from within Visual Studio IDE but fails when using vstest.console.exe and Microsoft Fakes

I have a solution, which contains numerous projects. Each of these projects has an associated test project which uses MSTest V2. Some of these test projects take advantage of Microsoft Fakes.
When I run the tests in the Visual Studio IDE, everything works fine. However, my build pipeline fails. I attempted to emulate what my build pipeline is doing and it also fails on my machine.
The error message I get is the following:
System.TypeLoadException: Could not load type
'System.Fakes.ShimDateTime' from assembly 'mscorlib.4.0.0.0.Fakes,
Version=4.0.0.0, Culture=neutral, PublicKeyToken=0ae41878053f6703'.
After playing around with the vstest.console.exe application, it seems that if I run each test assembly separately all of the tests pass, but if I attempt to pass in multiple assemblies which utilize Microsoft Fakes they fail.
vstest.console.exe "Path/To/First.dll" Passes
vstest.console.exe "Path/To/Second.dll" Passes
vstest.console.exe "Path/To/First.dll" "Path/To/Second.dll" Fails
vstest.console.exe "Path/To/First.dll" "Path/To/Second.dll" /InIsolation Fails
I'm not sure what is going on here or how to resolve this issue.
I eventually figured out what the problem was:
Test Project A had not defined System.DateTime in a Microsoft Fakes config file, so an assembly was generated named mscorlib.4.0.0.0.Fakes.dll which was missing the System.Fakes.ShimDateTime.
Test Project B had defined System.DateTime in a Microsoft Fakes config file, so an assembly was generated named mscorlib.4.0.0.0.Fakes.dll which contained the type System.Fakes.ShimDateTime.
This lead the following structure:
ProjectA.Tests/bin/Debug/
ProjectA.Tests.dll -- Contains the unit tests for Project A
mscorlib.4.0.0.0.Fakes.dll -- Does not contain System.Fakes.ShimDateTime
ProjectB.Tests/bin/Debug/
ProjectB.Tests.dll -- Contains the unit tests for Project B
mscorlib.4.0.0.0.Fakes.dll -- Does contain System.Fakes.ShimDateTime
I'm not sure what the Visual Studio IDE is doing differently, but the vstest.console.exe seems to load all of the assemblies, ignoring duplicates based on fully qualified names. That is, it loads the following files:
ProjectA.Tests/bin/Debug/ProjectA.Tests.dll
ProjectA.Tests/bin/Debug/mcsorlib.4.0.0.0.Fakes.dll
ProjectB.Tests/bin/Debug/ProjectB.Tests.dll
It ignored the file ProjectB.Tests/bin/Debug/mcsorlib.4.0.0.0.Fakes.dll, which had the type System.Fakes.ShimDateTime defined within it.
The only solution to this is to run a separate vstest.console.exe per test project (instead of all at once), or to ensure that the generated Microsoft Fakes assemblies (*.Fakes.dll) have the same types defined across the board, so it doesn't matter which version of mscorlib.4.0.0.0.Fakes.dll is loaded. And, since the Azure Pipelines VsTest task uses a single run of vstest.console.exe this is important to know.

Unit tests that are testing for View being returned are failing

.Net 4.5 MVC application - Unit tests that are testing for View being returned are failing with an error indicating it cannot find System.Web.WebPages on our build server:
Error Message:
Test method
CCSSWorkflow.Tests.CAHDAResearchControllerTest.CAHDAResearchDetailMethodReturnsCorrectView threw exception:
System.TypeInitializationException: The type initializer for 'System.Web.Mvc.ViewEngines' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
These same tests run fine from Visual Studio, they also run fine from the command line on my local machine utilizing vstest.
These same tests (same SVN build number) ran fine yesterday.
I do not have direct access to the build server, but I can ask questions. So far they have indicated there was no changes to the server in last two days.
Intermittent issues of that type may indicate missing binding redirect (it is possible that multiple project point to different versions and random sequence of loading at runtime may cause this).
If you have confirmed all references and binding redirects in your project are fine, and to take out the guess work out of the message you are seeing, ask them to enable Fusion on the build server - this will give you the details of what exactly is missing, if indeed you are dealing with a missing assembly.

C# DllImport Inconsistency

I am testing that I am using the correct dll interface for a ThirdParty.dll but using a mocked unmanaged dll in some unit tests. The ThirdParty.dll is imported using DllImport("ThirdParty.dll") inside the production code. The mock dll is placed in the same directory as the NUnit test code, the working directory of the command line set to the same directory as the Test Dll and mock dll, and then NUnit is called with a full path.
Example:
TestDirectory contains:
Test.dll
nunit.framework.dll
pnunit.framework.dll
ThirdParty.dll
and some other dependencies.
and the following is called:
C:\TestDirectory>ProgFiles\NUnit\nunit-console-x86.exe Test.dll /config:Release /framework:net-4.0
On our development machines the mock version of ThirdParty.dll is picked up fine and our tests pass but when we put the same code and directory structure on the customer computer it picks up the real installed version of the dll instead, which we also have installed on our dev machines but gets blocked by the mock one during unit tests.
I'm aware of the Search Order used by Windows, but I think that in both instances the DLL should be found in step 1 "The directory from which the application loaded.". I'm also aware of picking up the same name DLL if it is in memory, but I believe this applies if it is in the same process memory, which it should not be.
Does anyone have any ideas on what I could check or what might be causing this?
Thanks
The search order for dynamic link libraries can be found here. It's always the same, but it does depend on operating system settings, so with two different machines with different settings, you may get different results.
Use the fusion log viewer to get a more detailed view into how your assembly is being found. The viewer will list all paths your application is searching to load an assembly and where they were found. This always give me an answer when I have unexpected DLL dependency problems.

Getting started with vstest.console.exe System.IO.FileNotFoundException

I have a simple executable project and a Unit Test project all in the same solution in Visual Studio 2013. All my unit tests work fine in Visual Studio. I wanted to play* with the console app vstest.console.exe but am having a hard time getting going. I suspect I'm missing something very simple. I tried going to the directory where the actual .exe is and ran:
C:\BuildTest\Frame\Frame\obj\Debug>vstest.console.exe
C:\BuildTest\Frame\FrameUnitTests\obj\Debug\FrameUnitTests.dll
/Platform:x64 /Tests:ConstructorTest
and I got the error:
Starting test discovery, please wait...
Failed ConstructorTest
Error Message:
Test method FrameUnitTests.MainWindowPresenterTests.ConstructorTest threw
exception:
System.IO.FileNotFoundException: Could not load file or assembly
'Frame, Vers ion=3.0.0.0, Culture=neutral, PublicKeyToken=null' or one
of its dependencies. T he system cannot find the file specified.WRN:
Assembly binding logging is turned OFF.
I also tried running it from the actual directory where the unit test dll is:
C:\BuildTest\Frame\FrameUnitTests\obj\Debug>
and got the same results.
The error indicates that I need to somehow tell vstest.console where to find the main assembly that is being tested. How do I do this? Can someone point me to an example?
I'm interested in playing with vstest.console.exe for the following reason: I would like to get a printout of all my unit tests (about 80 of them) for use in documentation. I can't find a good way to do this. It occurred to me that vstest.console might be helpful for this. If there is another way to get a list of all my tests, I'd like to know. Admittedly, I could have simply typed every test title into MSWord in the time I've worked on this, but I'm a glutton for punishment and it might be nice to know how to use vstest.
I tried John Koerner's suggestion (see his answer) to get a list of tests and got the following results which might be a hint as to what I have going wrong:
C:\BuildTest\Frame\FrameUnitTests\obj\Debug>vstest.console.exe /ListTests:
FrameUnitTests.dll
Microsoft (R) Test Execution Command Line Tool Version 12.0.21005.1
Copyright (c) Microsoft Corporation. All rights reserved.
Test run will use DLL(s) built for framework Framework45 and platform X86. Follo
wing DLL(s) will not be part of run:
ACMFrameUnitTests.dll is built for Framework Framework45 and Platform X64.
Go to http://go.microsoft.com/fwlink/?LinkID=236877&clcid=0x409 for more detail
s on managing these settings.
Error: None of the provided test containers match the Platform Architecture and
.Net Framework settings for the test run. Platform: X86 .Net Framework: Frame
work45. Go to http://go.microsoft.com/?link for more details on managing these
settings.
If you only need a list of tests, you can simply run the following command:
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\ide\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" /ListTests:UnitTests.dll

Visual Studio 2010 Setup Project Settings

I have a solution that contains three projects; UI (winforms), Business Layer and Data Access Layer, and I have created a setup project. I have added UI project as a primary output, and other two projects (actually dlls) automatically added to application folder and these two projects appears under the Detected Dependencies folder in the solution.
After building the solution, I have installed the program. When I run the program, I get the following error:
"Could not load file or assembly 'xxxBL', Version = 1.0.0.0 Culture = neutral, PublicKey Token = null or one of its dependencies." What am I doing wrong?
First make sure the dll that failed to load is actually in the search path of your Application. If it is, run the Dependency Walker on the dll that failed to load to see why it failed to load. Like the error message says it is possible that one of the dll's dependencies failed to load. For instance, a common mistake occurs if you deploy a debug version of your dll. It would work on your development machine since it most likely would have whaterver SDK you used already installed, but on a fresh machine it would fail to load because the debug dlls are not installed. The Dependency Walker will allow you to find this sort of problem.

Categories

Resources