nunit and log4net - c#

I am unable to test my log4net library using nunit. I read the search results returned by Google but could not understand them.
This is the error that I am getting.
System.IO.FileNotFoundException : Could not load file or assembly
'log4net, Version=1.2.10.0, Culture=neutral,
PublicKeyToken=692fbea5521e1304' or one of its dependencies. The
system cannot find the file specified.
In my nunit test project I have added the reference to correct log4net dll that rest of the projects are using and added the configuration files but no luck.
My Console application and test web application that use the log4net libaray are working correctly.
I seem to only have problem with log4net nunit test project.
How can I get started with simple nunit test involving log4net library.

You should be accepting an ILog in whatever you're trying to test. Then you should mock it and pass it to whatever you're attempting to test. The version of log4net shouldn't matter at all. Your tests shouldn't even know log4net exists.
Using Rhinomocks, this would be:
MockRepository mocks = new MockRepository();
ILog mockLog = mocks.DynamicMock<ILog>();
Alternatively you could go with a stub:
ILog mockLog = MockRepository.GenerateStub<ILog>();

Check that Version of log4net.dll is same for your tests project and for projects which are referenced by tests (btw latest version of log4net is 1.2.11.0). Also verify that Copy Local is set to true.
If you are involving log4net library, then this is probably integration test, not unit test.

Double check the run-time log4net.dll file you have included. It looks like it could not match the .NET run-time CLR of your project. Check the target NET version of your app (Project -> Properties), and make sure it matches the target version of log4net.dll. Note version 1.2.11 of log4net includes binaries up to version 4.0, and also note client-profile versions are distinct than full versions, requiring their own specific dll files.

Related

NUnit TestEngine throws "Unable to load one or more of the requested types" when trying to explore assembly

I'm working on a tool that needs to extract the NUnit tests names that are contained in an assembly.
As I need the exact name of the tests when they are run, and NUnit's way of naming the tests is not straightforward, I use the NUnit TestEngine to explore the assembly.
Something like that :
Assembly testAssembly; //loaded somewhere else
using var testEngine = new TestEngine();
testEngine.WorkDirectory = Path.GetDirectoryName(testAssembly.Location);
var package = new TestPackage(testAssembly.Location);
using var runner = testEngine.GetRunner(package);
var testsFound = runner.Explore(new TestFilter(string.Empty));
I build the whole tool with one of our projects as test subject, and it works well.
But when I try it on other similar projects (.Net 6, NUnit test projects for a web API), I have the following error :
Unable to load one or more of the requested types.
Could not load file or assembly 'Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.
The tests run properly inside the Visual Studio, with VS test runner or Resharper.
The current directory is set to the bin folder.
Looking at the project, it seems that this is a implicit dependency of Microsoft.AspnetCore.Hosting (referenced by AppInsight)
But :
I don't see any version 6.0.0.
I have another similar project that loads properly and have the exact same dependencies
I can't find any Nuget package that has this version (highest is 2.2.0), so I can't force the reference.
The Assembly loads properly (with Assembly.LoadFrom()), it fails in NUnit, when it tries to call LoadTests
I can't find where this reference is needed and why one solution is working and others are not, while they are very similar !
I'm out of ideas to make it work, so I'm looking for suggestions.
Have you considered simply telling NUnit to produce the list of tests for you?
The --explore option followed by a file name creates XML output but without a following name it produces a readable list of names on the console. You can redirect the output to a file if that's what you want.
nunit3-console yourtests.dll --explore
UPDATE
Make sure you use the standard .NET Framework build of NUnit3-console with the above option, not the .NET 6.0 build. The standard runner creates whatever process is needed to properly explore the test assembly.

Castle Windsor - FileNotFoundException in Unit Tests

I’ve inherited an ASP.Net web application comprising of VB.Net projects. I’ve added a C# project to the solution, which references several of the VB.Net projects.
The application uses Castle Windsor as a DI container and dependencies are registered in one of the VB.Net projects.
In that VB.Net project. to avoid circular references, I use the “FromAssemblyNamed”, method to register the dependencies that are defined in my C# project:
container.Register(Classes.FromAssemblyNamed("x.y.z.TLBusinessLayerV2").BasedOn(Of IService).WithService.FromInterface().Configure(Function(c) c.LifeStyle.Transient))
This is working fine when I run the application.
However, there is an existing Unit Test project. In that I have added a reference to my C# assembly.
When I run all of the tests, some of the tests fail when they hit the code above with the following exception:
System.IO.FileNotFoundException: Could not load file or assembly x.y.z.TLBusinessLayerV2' or one of its dependencies. The system cannot find the file specified.
All of the assemblies referenced by the C# Assembly are also referenced by the Unit Test project.
The Target CPU for the VB.Net project, C# project and Unit Test project are all set to x86.
If I then run one of the failed tests individually, the test passes.
Q. Why are the Tests failing when I run them all?
Any help much appreciated.
The solution to this issue is to add a dummy class to the Unit Test project, that references a class in the assembly (loaded in "Classes.FromAssemblyNamed"). Something like:
Public Class DummyDependencies
Private Xyz As Object = GetType(<name of a class in target assembly>)
End Class
This appears to enforce the reference to the assembly.

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.

NuGet dependencies in MEF loaded assemblies

I am trying to code an application in C#.NET Core that can be extended using MEF. Currently, I am able to do that without any issues with libraries, that have no dependencies or have the same dependencies as the host app (so dependencies are already loaded). But, if I want to use a library with a NuGet reference, that is not used by the main app, the loading of this library fails on that reference.
How can I force the main app to load the missing NuGet dependency, if it tries to load an assembly with such reference? It seems to me as a pretty common use case, but I am lost here and cannot find a way out. Thanks.
For reference, I am posting the portion of the code.
[ImportMany]
private IEnumerable<Lazy<IService, IServiceMetadata>> _asrServices;
...
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(Path.Combine(Directory.GetCurrentDirectory(), "Services")));
CompositionContainer _container = new CompositionContainer(catalog);
...
foreach (Lazy<IService, IServiceMetadata> _service in _asrServices)
{
var _serviceInstance = _service.Value // here the loading fails
}
Jiri
.NET currently has two build "systems". One is the original project files, that import Microsoft.Common.props and Microsoft.CSharp.targets (assuming it's a c# project) and lots of XML in between, that has been around ever since .NET was first released, apparently in 2002. Since .NET Core was made generally available in 2016 there has been a new project system generally called SDK projects because the way a *proj file references the build system is though an Sdk element or attribute in the msbuild xml. Although it's off-topic, because there's a common bad assumption, I want to point out that although SDK projects were created for .NET Core, you can target the .NET Framework from SDK projects.
With the original project files, when you build, all the projects references get copied to the output directory. However, with SDK projects, only the project's assembly is copied to output (I'm not sure, but I think even content set to copy to output doesn't actually get copied on build). In order to get everything in a single directory, you should use the dotnet cli's publish command.
So, if you have a build script that builds your project and copies all the plugins somewhere, you should add a dotnet publish step to the script for each plugin using the SDK style project file.

Microsoft.Win32.ShimRegistryKey not working on build machine

I Have lots of unit tests where I shim the Microsoft.Win32.RegistryKey using Microsoft Fakes. When I run the build on my local machine the unit test passed. But if I run it on build machine the unit test fails with the following error for these tests.
System.TypeLoadException: Could not load type
'Microsoft.Win32.Fakes.ShimRegistryKey' from assembly
'mscorlib.4.0.0.0.Fakes, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=0ae41878053f6703'.
The curious thing is that both my local machine and build machine are 64-bit and the unit test project are targeting AnyCPU. Is there some configuration could be missing on the build machine?
I just has a similar issue when using Shims in multiple separate Unit test projects. Apparently the generated shims can overwrite each over or something like that.
Here's the instructions I followed to fix it:
Scroll to the middle of this page: https://msdn.microsoft.com/en-us/library/hh708916.aspx
It's under the heading of optimise build times, but use it to fix your problem too.
Because such assemblies rarely change on your machine, you can reuse the generated Fakes assemblies in other projects.
From your unit test projects, you can simply take a reference to the compiled Fakes assemblies that are placed under the FakesAssemblies in the project folder.
Create a new Class Library with the .NET runtime version matching
your test projects. Let’s call it Fakes.Prebuild. Remove the
class1.cs file from the project, not needed.
Add reference to all the System and third-party assemblies you need
Fakes for. and generate the fakes, edit the .fakes file if you like,
and build to generate the fake assemblies.
From your Unit Test projects Just make sure that you have a reference
to the Fakes runtime DLL: C:\Program Files\Microsoft Visual Studio
12.0\Common7\IDE\PublicAssemblies\Microsoft.QualityTools.Testing.Fakes.dll
Then for each assembly that you have created Fakes for, add a
reference to the corresponding DLL file in the
Fakes.Prebuild\FakesAssemblies folder of your project. (This folder
get created when you compile)
To confirm You will need to add the reference by Browsing to the
generated fake assembly..

Categories

Resources