Problem with Nunit 2.5 and AppDomain.CurrentDomain.SetPrincipalPolicy - c#

The following test works fine with .Net 3.5 + NUnit 2.4.8. But the same tests does not work using .Net 4.0 + Nunit 2.5.7.10213.
/// <summary>
/// This test fails with unexpected exception:
/// System.InvalidCastException : Unable to cast object of type
/// 'System.Security.Principal.GenericPrincipal' to type
/// 'System.Security.Principal.WindowsPrincipal'.
/// </summary>
[Test]
public void GiventATest_WhenSettingDomainPrincipal_AccessingThreadcurrentPrincipalWorks()
{
AppDomain.CurrentDomain.SetPrincipalPolicy(System.Security.Principal.PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal currentUserWindowsPrincipal = (WindowsPrincipal)Thread.CurrentPrincipal;
}
The wierd thing is that after the test has failed once, I can run the tests again and it works until I reload the test assembly. And then, it fails again on the first attempt.

add this before your test:
NUnit.Core.TestContext.CurrentPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
You will need to add a reference to NUnit.Core.dll if you do not have it already. Be aware that there are two classes TestContext, one in NUnit.Framework namespace and one in NUnit.Core namespace

Related

Is it possible to use xUnit with LINQPad?

Is it possible to use xUnit with LINQPad?
It would be great to be able to write some tests for concepts being designed in LINQPad first. It's easier than adding yet another ConsoleApp23423894238 just to be able to quickly write some unit tests.
Yes, it is possible to use xUnit with LinqPad. I have updated this answer to give you the latest information, but the original answer I gave also gives you some insights and links regarding the usage of xUnit, so I kept it for your reference.
UPDATE: Latest version of LinqPad 6 or 7 (since V 6.9.x and higher, see 6.9 Release Notes section) has now built-in XUnit support via the new menu item Query / Add XUnit Test Support. This will add a query with required boilerplate code referenced via #load so you can start testing facts and theories instantly. You can run the example test method by pressing Alt+Shift+T.
For example, add the following new theory to the boilerplate code (right after the main method, put it inside the private::Tests region):
#region private::Tests
[Theory]
[InlineData(1)]
[InlineData(3, 6)]
[InlineData(5, 7, 9)]
void OddNumbers(params int[] values)
{
static bool IsOdd(int value) => value % 2 == 1;
foreach (var value in values)
{
Assert.True(IsOdd(value), $"IsOdd({value}) is false");
}
}
#endregion
Press Alt+Shift+T to run all tests and check the result.
Note: It also adds a file XUnit.linq to your query directory the first time you add XUnit Test support - this is a mini library to support xUnit tests and you should not touch it unless you know exactly what you're doing. For example, you can modify this file to change the way the test summary is being displayed (for example, you can add the parameter Func<UserQuery.TestResultSummary, bool> filter = null to the method RunTests and add .Where(filter) inside the query if filter is not null. This allows you to filter the results of the test summary).
For example: RunTests(filter: f => f.MethodName.StartsWith("Unit")); will only display the tests in the summary which names start with "Unit".
Dynamically skippable unit tests
You can modify the xunit script LinqPad 6 provides to support skippable unit tests (NUGET package XUnit.SkippableFact, detailed description see the link "dynamically skipping test and theory" at the end of this answer).
Make the following changes in xunit:
function RunTests - add:
runner.OnTestSkipped = info => AddTestResult(info);
class TestResultSummary - add:
public bool Skipped() => _testInfo is Xunit.Runners.TestSkippedInfo;
class TestResultSummary / public object Status - add:
_testInfo is Xunit.Runners.TestSkippedInfo ? Util.WithStyle ("Skipped", "color:orange") :
Those changes will enable the xunit script to show when a test was skipped in the results.
To test it, load the NUGET package XUnit.SkippableFact via F4, then add the test framework and finally add the tests:
[SkippableFact]
void Test_Xunit3()
{
Skip.If(true, "skipping");
Assert.True(1 + 1 == 2);
}
[SkippableTheory]
[InlineData(1)]
[InlineData(2)]
void Test_Xunit4(int x)
{
Skip.If(x==2, "skipping");
Assert.True(1 + 1 == 2);
}
Note: Those changes will also work with the plain XUnit. So adding the changes to the code does not harm.
Now if you like, continue reading the original answer (with some useful hints at the end):
Two answers pointed me into the right direction, but the descriptions haven't been complete enough, so I had to experiment a bit. To save you that time, I am describing what I did; I have now working solutions for LinqPad 5 and LinqPad 6 (and 7).
LinqPad 5 - for .NET
Based on what Tom wrote, I was able to get it working with LinqPad 5 (v5.42.01).
There are some more steps required, which aren't obvious and not explained in the accepted answer, so I'll describe what helped on my side.
First of all, you will need to use the paid version of LinqPad, because only then you are able to load NUGET packages.
To load the required packages in LinqPad, press F4. The query properties dialog opens up. In that dialog, click Add NUGET....
The NUGET dialog opens up. In the middle of the NUGET dialog, there is a search textbox. Search for xUnit.Net - once it got displayed, click Add to query, wait until it loaded, then click on Add namespaces. Then do the same for Xunit.Runner.LinqPad.
Then close the NUGET dialog, but keep the query properties open. You need to to there to the Advanced tab: Enable (tick-mark) "Copy all non-framework references to a single local folder." Now you can close the query properties dialog.
Import the following example into the query editor (C# Program mode):
void Main()
{
// Press F4, go to Advanced, then
// tick-mark "Copy all non-framework references to a single local folder"
var me = Assembly.GetExecutingAssembly();
var result = Xunit.Runner.LinqPad.XunitRunner.Run(me);
result.Dump("Xunit runner result");
}
/// <summary>
/// This test class is there for demo purpose, so developers can
/// see how to write test methods.
/// It also verifies that XUnit itself is functioning correctly.
/// </summary>
public class A_XUnitSelfTest
{
[InlineData(2)]
[InlineData(3)]
[Theory]
public void Test_Theory(int a)
{
Assert.True(a == 2 || a == 3); // succeeds
}
[Fact]
public void Test_Fact()
{
Assert.False(1 == 0); // succeeds
}
}
Run it and you will see the output of the test runner.
Running 3 of 3 tests...
Finished: 3 tests in 0,003s (0 failed, 0 skipped)
Modify the test to see how it looks like if a test fails by changing the assert in the Test_Fact() to Assert.False(1 == 1);, then run it again. It should show this time:
Running 3 of 3 tests...
[FAIL] UserQuery+A_XUnitSelfTest.Test_Fact: Assert.False() Failure
Expected: False
Actual: True
at Xunit.Assert.False(Nullable`1 condition, String userMessage)
at Xunit.Assert.False(Boolean condition)
at UserQuery.A_XUnitSelfTest.Test_Fact() in C:\Users...\AppData\Local\Temp\LINQPad5_oyxxqxbu\query_mxsmky.cs:line 62
Finished: 3 tests in 0,005s (1 failed, 0 skipped)
LinqPad 6 - for .NET Core
LinqPad 6 is different, because it is based on .NET Core and hence does require different libraries.
Start with this:
void Main()
{
// Press F4, go to Advanced, then
// tick-mark "Copy all non-framework references to a single local folder"
var me = Assembly.GetExecutingAssembly();
var result = Xunit.Runner.LinqPad.XunitRunner.Run(me);
result.Dump("Xunit runner result");
}
/// <summary>
/// This test class is there for demo purpose, so developers can
/// see how to write test methods.
/// It also verifies that XUnit itself is functioning correctly.
/// </summary>
public class A_XUnitSelfTest
{
[InlineData(2)]
[InlineData(3)]
[Theory]
public void Test_Theory(int a)
{
Assert.True(a == 2 || a == 3); // succeeds
}
[Fact]
public void Test_Fact()
{
Assert.False(1 == 0); // succeeds
}
}
Then add xUnit.net, xUnit.net [Core Unit Testing Framework] and xUnit.net [Runner Utility] and all their namespaces via the F4 dialog (details see LinqPad 5 sesion) and finally copy the XUnit runner source code as mentioned by #ramiroalvarez to the end of the xUnit test example above:
XUnit runner source code
Enable "copy all nuget assemblies to a single local folder" in the F4 dialog, Advanced tab ... that should be enough, but it isn't so read on:
If you try it, it throws the exception InvalidOperationException("Please enable the shadow folder option for none-framework references (F4 -> Advanced).") in the source code.
Now I looked into the XUnit runner, and found that if you comment out 2 lines of code then it is running fine:
Original code (located in method GetTargetAssemblyFilename):
if (shadowFolder != xunitFolder
|| Directory.GetFiles(shadowFolder, "xunit.execution.*.dll").Length == 0)
{
throw new InvalidOperationException("Please enable the shadow folder option ...");
}
// ...
var targetAssembly = Path.Combine(shadowFolder, Path.GetFileName(assemblyFilename));
//Console.WriteLine($"Copy \"{ assemblyFilename }\" -> \"{ targetAssembly }\"");
File.Copy(assemblyFilename, targetAssembly, true);
Comment the lines
// ...
// throw new InvalidOperationException("Please enable the shadow folder option ...");
// ...
// File.Copy(assemblyFilename, targetAssembly, true);
and you're done! (Tested with v6.8.3 version of LinqPad 6, X64 version)
Hints:
Hint 1:
You can append the xUnit runner to your code as described, but there is a more elegant way in LinqPad 6:
Save a copy containing only the xUnit.Runner source code in the same path as your unit test files with the file name xUnit.Runner.LinqPad6.linq.
Then, add the following to the top of your test code:
Now you have cleaned up your code! Every time you create a new test, just remember to add the #load command.
Hint 2:
To be able to skip facts statically, add the following 2 attributes to the code of the test runner:
/// <summary>
/// Skip a Fact (you can override it by setting OverrideSkip=true)
/// </summary>
public class SkipFactAttribute : FactAttribute
{
/// <summary>
/// Override SkipFact: Set OverrideSkip=true to run even skipped tests
/// </summary>
public static bool OverrideSkip = false; // set to true to ignore skip
/// <summary>
/// Constructor. Used to set skip condition.
/// </summary>
public SkipFactAttribute()
{
if (!OverrideSkip) Skip = "Skipped Fact";
}
}
/// <summary>
/// Skip a Theory (you can override it by setting OverrideSkip=true)
/// </summary>
public class SkipTheoryAttribute : TheoryAttribute
{
/// <summary>
/// Override SkipTheory: Set OverrideSkip=true to run even skipped tests
/// </summary>
public static bool OverrideSkip = false; // set to true to ignore skip
/// <summary>
/// Constructor. Used to set skip condition.
/// </summary>
public SkipTheoryAttribute()
{
if (!OverrideSkip) Skip = "Skipped Theory";
}
}
This is useful, if you want to skip tests. To skip a test, simply replace [Fact] by [SkipFact] or [Theory] by [SkipTheory].
If you're busy writing a test and you want to test only that single test, set all attributes to [SkipFact] or likewise [SkipTheory], except the single one you're writing currenlty.
Then, to quickly run all the tests again from time to time - without having to change each and every single attribute - add the following to the initialization part of your test suite (see global setup for startup and teardown):
public class TestsFixture : IDisposable
{
public TestsFixture() // running once before the tests
{
// true: Ignore Skip and run all tests, false: Skip is effective
SkipFactAttribute.OverrideSkip = true;
SkipTheoryAttribute.OverrideSkip = true;
}
public void Dispose() // running once, after the tests
{
// teardown code
}
}
If you're done, restore the [Fact]/ [Theory] attributes and set the .OverrideSkip variables back to false.
NOTE: In case you want to skip facts based on a runtime condition, take a look at dynamically skipping test and theory.
More about unit testing
For some advanced topics about unit testing with xUnit, I recommend to read:
xunit tests in net core
global setup for startup and teardown
shared context
running tests in parallel
running tests in prioritized, specified order
configuring with json
configuring with xml
skipping Test and Theory // description works for TheoryAttribute too
dynamically skipping test and theory
xUnit Theory: Working With InlineData, MemberData, ClassData
If you want to use it with Visual Studio, you can find infos here.
Possible? Sort of.
This is neither a main use case of LINQPad nor of unit testing.
Regarding LINQPad, you could use an existing test runner but probably the only ones that could be integrated with LINQPad are console runners. A test runner is not a trivial program. Try Xunit.Runner.LinqPad.
As for needing to "write some tests for concepts being designed", consider that you might not be getting enough out of your unit testing workflow if you don't find them valuable enough to create a project and keep it in source control. One way to get more value is to use Behavior-Driven Development (BDD) and if you want to write the requirements in a business-readable language, try something like SpecFlow.
Thanks to asherber, xunit now works with linqpad6 (netcore).
https://github.com/asherber/Xunit.Runner.LinqPad/blob/master/Xunit.Runner.LinqPad/XunitRunner.cs
It is important within the query properties, check "copy all nuget assemblies to a single local folder" otherwise, you will have the following error "InvalidOperationException: Please enable the shadow folder option for none-framework references"
I just tried to open a LINQPad query file that tried to load the xunit package and got an error which has never happened to me in using LINQPad for years. So my answer is no.

Missing [assembly:RuntimePlugin] attribute in SpecFlowPlugin

I've created a SpecFlow Plugin following their page below. And have created a Generator Plugin as I needed to modify the auto generated code behind my features.
https://github.com/techtalk/SpecFlow/wiki/Plugins.
SpecFlowPlugin Code
[assembly: GeneratorPlugin(typeof(SpecFlowSpiraAdapterPlugin))]
namespace SpiraTest.SpecFlowPlugin
{
/// <summary>
/// A adapterpPlugin is needed to use a custom MSTest generator with SpecFlow.
/// </summary>
public class SpecFlowSpiraAdapterPlugin : IGeneratorPlugin
{
/// <summary>
/// By implementing the Initialize- Method on the IGeneratorPlugin interface, you get access to the GeneratorPluginEvents and GeneratorPluginParameters
/// </summary>
/// <param name="generatorPluginEvents"></param>
/// <param name="generatorPluginParameters"></param>
public void Initialize(GeneratorPluginEvents generatorPluginEvents, GeneratorPluginParameters generatorPluginParameters)
{
generatorPluginEvents.CustomizeDependencies += GeneratorPluginEvents_CustomizeDependencies;
}
private void GeneratorPluginEvents_CustomizeDependencies(object sender, CustomizeDependenciesEventArgs e)
{
e.ObjectContainer.RegisterTypeAs<MSTestCustomGenerator, IUnitTestGeneratorProvider>();
}
}
}
Problem
I'm getting an error message when trying to run my tests indicating that i don't have the below attribute.
[assembly:RuntimePlugin] attribute
However I don't need that attribute as I have the [assembly: GeneratorPlugin] attribute instead.
No idea why it's saying that. Any ideas?
Message: Class Initialization method
MiJobsAdminPortal.UITests.Login.LoginFeature.FeatureSetup threw
exception. TechTalk.SpecFlow.SpecFlowException:
TechTalk.SpecFlow.SpecFlowException: Missing [assembly:RuntimePlugin]
attribute in SpiraTest.SpecFlowPlugin, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null. Please check
http://go.specflow.org/doc-plugins for details..
For SpecFlow every plugin is a Generator and a Runtime plugin, except you configure it otherwise. This is the code for that: https://github.com/techtalk/SpecFlow/blob/master/TechTalk.SpecFlow/Infrastructure/ContainerBuilder.cs#L127
As an example for configuration, have a look at the configuration of the SpecFlow+Excel plugin, which is also only a generator plugin.
<specFlow>
<plugins>
<add name="SpecFlow.Plus.Excel" type="Generator" />
</plugins>
</specFlow>
You have to specify the type as Generator. If not SpecFlow is always searching for both plugin types.
This behaviour is not documented, but is there since years. I will update the documentation in the next days.
Full disclosure: I am one of the maintainers of SpecFlow & SpecFlow+

Microsoft.Practices.EnterpriseLibrary.Logging raises errors in Release but not in Debug

I've got a ClickOnce project I've just updated from VS2010 to VS2015 that has a reference to the above in it (eg Using Microsoft.Practices.EnterpriseLibrary.Logging;).
When I run the project in Debug, it doesn't flag that reference or it's uses at all.
When I swap to Release, the Using statement is flagged saying "Error CS0234 The type or namespace name 'Practices' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)"
I've tried to install the Enteprise Logging library from NuGet but it fails saying it doesn't target .Net 4 (the targeted framework hasn't been changed by me between updating VS versions)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Diagnostics;
namespace BlahBalh.BudgetReporting.Common
{
/// <summary>
/// Handles the writing of information to the log (Event Viewer).
/// Uses the Microsoft Best Practices Library, see App.config for loggin options.
/// </summary>
public class Log
{
/// <summary>
/// Constructor - private as this is a static class
/// </summary>
private Log() { }
/// <summary>
/// Add the information to the log.
/// Use for general information messages.
/// </summary>
/// <param name="Title">Message Heading</param>
/// <param name="Message">Detailed information.</param>
public static void LogInformation(string Title, string Message)
{
LogEntry logEntry = new LogEntry();
logEntry.Title = Title;
logEntry.Message = Message;
logEntry.Priority = 0;
logEntry.EventId = 1;
logEntry.Severity = TraceEventType.Information;
logEntry.Categories.Add("General");
WriteEntry(logEntry);
}
etc...
I've also tried to find the Assembly reference area but can't see it in VS2015 (has it been replaced by NuGet?)
Any pointers greatly appreciated.

MissingMethodException Plugin CRM2011

I found a couple of suggestions on this question but I can't get it on my problem.
We got a .ddl which replaces placeholders in a word file and returned a memorystream. This works fine in a deliverd Test Application with a WPF FrontEnd.
Now we need this solution in a CRM2011 context. I added a reference to this .dll file in my CRM Project, build the logic exactly the way as seen in the example and boom a MissingMethodException appears.
I debuged to the point where the Exception is thrown and found somethine like this:
readonly Dictionary<Type, object> typeMap = new Dictionary<Type, object>();
/// <summary>
/// Returns an instance of the DataService implementing the <typeparamref name="TService"/> interface
/// </summary>
/// <typeparam name="TService">type of the interface for the DataService</typeparam>
/// <returns></returns>
public TService For<TService>()
{
if (typeMap.ContainsKey(typeof(TService)))
{
object value = typeMap[typeof(TService)];
if (value is Type)
{
return (TService)Activator.CreateInstance((Type)typeMap[typeof(TService)]);
}
return (TService)value;
}
return Activator.CreateInstance<TService>();
}
The line Activator.CreateInstance(); throws the Exception. I have absolutely no idea what is going wrong here and why this piece of code works fine on the test app.
I'm assuming it's because you are either attempting to create a Static class, or a class without an empty constructor. Add try catch that displays the type that is attempting to be created to narrow down what is happening.

The type 'InversionOfControl.IOC' exists in both 'InversionOfControl.dll' and 'InversionOfControl.dll'

I have a project called InversionOfControl. That project has a class called IOC. It looks like this:
/// <summary>
/// This class is used to expose the unity container to the application.
/// </summary>
public class IOC
{
/// <summary>
/// The actual unity container for the app.
/// </summary>
public static IUnityContainer Container { get; set; }
}
All my projects that need to resolve unity injections have a reference to this class. Lately I have started getting this error:
Value cannot be null.
Parameter name: container
on normal resolves:
ITransmitModel transmitModel = IOC.Container.Resolve<ITransmitModel>();
When I try to inspect IOC.Container, the value in the watch window is:
The type 'InversionOfControl.IOC' exists in both 'InversionOfControl.dll' and 'InversionOfControl.dll'
I have looked in my output folder and there is only one InversionOfControl.dll file. (I even cleaned my solution and double checked the folder was empty. I then rebuilt and checked again that there is only one.)
Why does it think there are two dlls called InversionOfControl.dll?
A way to check what module is loaded at run-time is "Debug->Windows->Modules" and check out where the DLL in question is loaded from. Make sure you are not loading 2 assemblies with different versions.
As a next step I would do search for all files with this name to see if there are suspicious copies ("cd /d c:\ & dir /s /b InversionOfControl.dll").

Categories

Resources