I have a class which contains an internal helper such as following code:
[assembly: InternalsVisibleTo("Tests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
namespace NS.B
{
public class A {
internal readonly B _bHealper;
public int GetBag(string s1, string s2){
return _bHelper.GetBag(s1, s2);
}
}
}
[assembly: InternalsVisibleTo("Tests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
namespace NS.B
{
internal class B
{
public int GetBag(string str1, string str2){
/// do some work
return result;
}
}
}
then I try to mock my helper inside A class and test A class GetBag function by this code:
[Fact]
public void checkBaggageRule()
{
var repo = Substitute.For<A>();
repo._bHelper.GetBag(Arg.Any<string>(), Arg.Any<string>()).Returns(30);
var result = repo.GetBag("oo", "L");
Assert.True(result != null);
Assert.True(result == 30);
}
but I am getting this exception while I debug my test:
NSubstitute.Exceptions.UnexpectedArgumentMatcherException : Argument
matchers (Arg.Is, Arg.Any) should only be used in place of member
arguments. Do not use in a Returns() statement or anywhere else
outside of a member call.
how can I mock this internal member and pass my test?
There's not quite enough code in the sample to tell for sure, but I'm not sure that the internal keyword is causing the problem here. If you make them all public instead do you get the same error?
There are a few other possible issues that could be causing problems for you here.
First, try installing the NSubstitute.Analyzers package, which will detect issues like trying to substitute for non-virtual members.
Next, the sample code does not show how A._bHelper gets initialised. Let's update it to use constructor injection, and we'll substitute for the dependency rather than the entire class under test (as pointed out by #Nkosi in the comments).
public class A
{
public A(MssqlEntityHelper helper) { _bHelper = helper; }
internal readonly MssqlEntityHelper _bHelper;
public int GetBag(string s1, string s2) {
return _bHelper.GetBag(s1, s2);
}
}
// Tests:
[Fact]
public void SampleTest() {
var repo = new NS.B.A(Substitute.For<NS.B.MssqlEntityHelper>());
repo._bHelper.GetBag(Arg.Any<string>(), Arg.Any<string>()).Returns(30);
var result = repo.GetBag("oo", "L");
Assert.True(result == 30);
}
As the NSubstitute.Analyzers package will point out, MssqlEntityHelper.GetBag() will need to be made virtual in order for NSubstitute to work with it:
public class MssqlEntityHelper {
public virtual int GetBag(string str1, string str2) { ... }
}
Those changes will get a passing test based on the sample code provided. The exact exception you are seeing may be as a result this test or problems in other tests, perhaps attempting to substitute for non-virtual members in earlier tests. Installing the NSubstitute.Analyzers package will hopefully help you find these cases. If this still doesn't resolve the problem there are a few other debugging steps we can try (running the test in isolation, running a single fixture, looking at test logs to see test execution order and seeing if preceding tests are causing problems that bleed into this test, etc.).
Related
I've found a number of question regarding renaming tests in NUnit, but none that mention how to do so while using TestFixtureSource.
I am using the [TestFixtureSource] attribute to configure parameterized tests, like this:
[TestFixtureSource(nameof(GetTestParams))]
public class MyTestClass
{
private Mock<IMyDependency> _mockDependency;
private TestData _data;
private MyClass _objectUnderTest;
public MyTestClass(TestData data)
{
_data = data;
}
public static IEnumerable<TestData> GetTestParams()
{
yield return new TestData(1, 2, 3);
yield return new TestData(4, 5, 9);
yield return new TestData(7, 8, 15);
}
[SetUp]
public void SetUp()
{
_mockDependency = new Mock<IMyDependency>();
_mockDependency.Setup(d => d.GetNum()).Returns(_data.A);
_objectUnderTest = new MyClass(_mockDependency.Object);
}
[Test]
public void RunTest()
{
var result = _objectUnderTest.doSomething(_data.B);
Assert.That(result, Is.EqualTo(_data.C));
}
}
public class TestData
{
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }
public TestData(int a, int b, int c)
{
A = a;
B = b;
C = c;
}
}
public class MyClass
{
private readonly IMyDependency _dependency;
public MyClass(IMyDependency dependency)
{
_dependency = dependency;
}
public int doSomething(int b)
{
return _dependency.GetNum() + b;
}
}
public interface IMyDependency
{
int GetNum();
}
My issue is that all test cases appear to have the same name in the results. They are all simply called "RunTest", which makes it difficult to determine which tests are failing other than simply counting the number of the test and then counting my yield returns to find the correct one.
I would love to be able to set the test name programmatically using an additional property in the TestData class. I attempted to do this using TestContext.CurrentContext.Test.Name = _data.Name, but it turns out this property is readonly so I can't set it.
Is there a way to rename my tests programmatically while using TestFixtureSource?
You need to consider the sequence of execution...
Your TestFixtureSource runs to define what fixture instances will be created.
If you have any TestCaseSources, that code is run to define what tests will be added to the fixture.
*** At this point, the structure of your tests (namespaces, fixtures, test cases) is completely defined and can't be changed. Any overridden test names are already in place.
At this point, the tests start to run. In the console runner, it happens immediately. In a GUI or under VS it happens when the user clicks run. In the second case, it may happen multiple times.
Any OneTimeSetup runs
For each test in the fixture
Setup Runs
The test itself runs (provided Setup didn't throw)
Teardown Runs
Any OneTimeTeardown runs
Key thing here is the break between loading (aka creating or discovering) the tests and running them. Nothing can happen in steps 4 - 6 to change what was done in steps 1 and 2.
Regarding changing the name... It's a constraint within NUnit that users may only change the name of test cases. The part that comes before the test name ... including the displayed name of the fixture ... is invariable because NUnit relies on it. Changing that would give us a different framework, or at least a version of NUnit with breaking changes.
If I understand correctly, you currently have something like this:
but you would prefer something like this:
This is achievable by overriding the ToString() method of the class whose type is the test fixture's parameter - TestData in your code. For example:
public class TestData
{
<...>
public override string ToString() => $"A: {A}, B: {B}, C: {C}";
}
Doing this (with NUnit 3.8 installed) produces the sample output above.
(Caveat: Charlie led the NUnit team for about 13 years and says this can't be done, so even if I've understood the question correctly it's possible that this technique is inadvisable; use at your own risk! But I hope it helps.)
Edit: Please see comments below, especially Charlie's note that this approach should only be taken with test classes, not production classes.
I'm trying to add tests to a webforms project. There's a static method to grab lines from resource files. One of the classes I'm trying to test, relies on grabbing text from the resource file.
public static class MyStaticClass {
public static string getText(String name)
{
String s = HttpContext.GetGlobalResourceObject("MyResources", name).ToString();
return s;
}
}
public class ClassUnderTest
{
// returns: "Hey it's my text"
private string _eg = MyStaticClass.getText("label_in_resources.resx_file")
}
class UnitTests
{
[Test]
public void TestMyClass()
{
ClassUnderTest _cut = new ClassUnderTest();
// errors out because ClassUnderTest utilizes getText
// which requires HttpContext.GetGlobalResourceObject
// ... other stuff
}
}
Note: these are simplistic examples.
The issue is that I get a Test Failed with the message:
Message: System.NullReferenceException : Object reference not set to an instance of an object.
With my sleuthing, I've determined that this is because HttpContext is null during these tests.
I've looked at quite a few SO posts on mocking HttpContext but I don't think that I fully understand what exactly they're doing as they're typically dealing with MVC and not Webforms. Still most of them use HttpContextBase and/or HttpContextWrapper but again, I'm not sure how to implement them.
Also - I'm not directly testing the getText method. I know it works. I'm testing a class that uses it. Will mocking the HttpContext even help in this situation?
I do realize that this is sort of a hybrid of a unit test / integration test, so if this isn't the best way, I'm all ears... or.. eyes rather.
Edit
For now, I modified my getText method to return the key (name) if the result of HttpContext.GetGlobalResourceObject is null. Then I updated my tests to expect the key instead of the value. It's not ideal, but it works and allows me to continue. If there's a better way, please let me know.
public static class MyStaticClass {
public static string getText(String name)
{
String s = HttpContext.GetGlobalResourceObject("MyResources", name);
return s != null ? s.ToString() : name;
}
}
Original answer with Fakes (see below for dealing with removing static)
So there's one caveat that I completely forgot about until I just tried to do this. I am pretty sure Fakes still requires Enterprise version of VS. I don't know if there's a way to get it to work with NUnit, but when you aren't able to change the code sometimes you have to just deal with it.
Here's an example of Shimming your static method. You don't need to worry about HttpContext (yet) since you aren't using it directly. Instead you can Shim your getText(string) method.
Actual Business Project
namespace FakesExample
{
public class MyStaticClass
{
public static string GetText(string name)
{
throw new NullReferenceException();
}
}
}
Your Unit Test Project
using System;
using Microsoft.QualityTools.Testing.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace FakesExampleTests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
using (ShimsContext.Create())
{
FakesExample.Fakes.ShimMyStaticClass.GetTextString = (s) =>
{
return "Go away null reference";
};
Console.WriteLine(FakesExample.MyStaticClass.GetText("foo"));
}
}
}
}
I actually ran this so I know it works. What happens is that even though GetText will always throw a NullReferenceException when called, our Shim of it returns our own custom message.
You may have to make a Visual Studio Test Project.
In your Unit Test project, right-click your reference and say "Add Fakes". It will generate all of the Shims and Stubs for your assembly.
Process of removing the static
The best solution is to actually work towards removing the static. You've already hit one major reason to not use them.
Here's how I would go about removing the static and removing the dependency on HttpContext
public interface IResourceRepository
{
string Get(string name);
}
public class HttpContextResourceRepository : IResourceRepository
{
public string Get(string name)
{
return HttpContext.GetGlobalResourceObject("MyResources", name).ToString();
}
}
public class MyFormerStaticClass
{
IResourceRepository _resourceRepository;
public MyFormerStaticClass(IResourceRepository resourceRepository)
{
_resourceRepository = resourceRepository;
}
public string GetText(string name)
{
return _resourceRepository.Get(name);
}
}
I would then leverage Dependency Injection to handle the creation of my HttpContextResourceRepository and MyStaticClass (which should probably also be interfaced) in the actual business code.
For the unit test, I would mock the implementation
[TestFixture]
public class UnitTest1
{
[Test]
public void TestMethod1()
{
var repoMock = new Mock<IResourceRepository>();
repoMock.Setup(repository => repository.Get("foo")).Returns("My Resource Value");
var formerStatic = new MyFormerStaticClass(repoMock.Object);
Console.WriteLine(formerStatic.GetText("foo"));
}
}
Going this route, you can create any number of IResourceRepository implementations and swap them whenever you want.
I'm trying to use the InternalsVisibleTo to allow me to test a utility / helper method from a separate Test assembly. When I try and call an internal method with a dynamic parameter I get the error "RuntimeBinderException was unhandled ... is inaccessible due to its protection level."
I believe I am using the InternalsVisibleTo attribute correctly as I am able to test other internal methods that do not use dynamic parameters. The following code illustrates the scenario where only the TestInternalMethodWithDynamic test fails as shown below. I have repeated the tests using instance methods instead of static and that made no difference.
The .NET technology is Silverlight 5 and I am using the Silverlight Unit Test Framework to execute the tests. I need to use dynamic parameters due to the Excel automation requirements of the project.
Edit: I have tested the same call using .NET 4 class library assemblies and it is successful so the problem seems to be specific to Silverlight.
Example utility class...
public class Utility
{
internal static int InternalMethodWithDynamic(dynamic parameter) {
return (int)parameter;
}
internal static int InternalMethodWithInteger(int parameter) {
return parameter;
}
public static int PublicMethodWithDynamic(dynamic parmater) {
return (int)parmater;
}
public static int PublicMethodWithInteger(int parmater) {
return parmater;
}
}
And the test class...
[TestClass]
public class UtilityTest
{
[TestMethod]
public void TestInternalMethodWithDynamic() {
dynamic parameter = 10;
Assert.AreEqual(10, Utility.InternalMethodWithDynamic(parameter));
}
[TestMethod]
public void TestPublicMethodWithInteger() {
int parameter = 10;
Assert.AreEqual(10, Utility.PublicMethodWithInteger(parameter));
}
[TestMethod]
public void TestPublicMethodWithDynamic() {
dynamic parameter = 10;
Assert.AreEqual(10, Utility.PublicMethodWithDynamic(parameter));
}
[TestMethod]
public void TestInternalMethodWithInteger() {
int parameter = 10;
Assert.AreEqual(10, Utility.InternalMethodWithInteger(parameter));
}
}
Workaround:
This isn't ideal but you can cheat a bit and still test the underlying logic of the method by passing the parameter as something other than dynamic (eg. one of the .NET Integral Types). I can't say I understand the dynamic type and implicit type conversion well enough to explain exactly what is happening but this seems to bypass the access modifier checks somehow. At least I don't need to make the method public. The modified test below now passes.
I think this is an acceptable workaround for my scenario but there may be some edge cases related to type conversion in other situations.
[TestClass]
public class UtilityTest
{
[TestMethod]
public void TestInternalMethodWithDynamic() {
int parameter = 10;
Assert.AreEqual(10, Utility.InternalMethodWithDynamic(parameter));
}
}
Is it possible to skip all tests from a specific class like in NUnit
[TestFixture]
[Ignore("Reason")]
public class TestClass {
}
No - there is no such facility at present, and the last time it was requested it was considered too low value to add,
One quick way of achieving the effect in xUnit is to comment out the public - private classes are not reflected over (obviously it won't appear on the skip list that way though).
UPDATE: Another way is to put a TraitAttribute on the class and then (assuming you're using the xunit.console runner) filter it out by running with /-trait traitName. (e.g. you can achieve ExplicitAttribute, some aspects of the BDD frameworky technique of Pending tests and similar semantics that way - of course the big problem is they don't show up in any reports when using any of these filtering techniques)
UPDATE 2: You can do
const string skip = "Class X disabled";
[Fact(Skip=skip)]
void Test() {}
Then you can change to to const string skip = null to undo the skip. The (dis)advantage of this is that the test is still shown as a Skipped test in the test list, generally with a reason included in the test run report (vs making it private which makes it likely to be forgotten)
Here is my hack to avoid error xUnit1000: Test classes must be public (checked on single Fact, I think Theories can be hacked this way, too).
// Uncomment to enable tests
//public class FactSwitch : FactAttribute { } // public! ahh, a bug!
// Uncomment to disable tests
internal class FactSwitch : Attribute { }
public class MyTests
{
[FactSwitch]
public void MyTest1()
{
"it".ShouldBe("it");
}
}
(3 years later)
While searching for the same solution I found there are better ways to do the same.
Let's rewrite the example above in a way Ruben Bartelink suggested (continuation of his idea).
public class MyTests
{
//const string SkipOrNot = null; // Run all tests
const string SkipOrNot = "reason"; // Skip all tests
[Fact(Skip = SkipOrNot)]
public void MyTest1()
{
"it".ShouldBe("it");
}
}
Nathan Cooper suggested a good improvement for my idea:
public class MyTests
{
// Uncomment to disable tests
//private class FactAttribute : Attribute { }
[Fact]
public void MyTest1()
{
"it".ShouldBe("it");
}
}
So I like both ideas from Ruben and Nathan. There is a subtle difference between using Skip="something" (Ruben) and not using Skip at all. Using "Skip" will put all your tests in a "Skipped tests" warning zone, while "FactAttribute : Attribute" will hide them.
I've found yet another way of temporary disabling entire class without compiler warning.
Disabled:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "xUnit1000:Test classes must be public", Justification = "Disabled")]//*/
/*
public /**/class DatabaseTests
{
}
to enable move the /* one line up (i.e. using alt+up):
/*
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "xUnit1000:Test classes must be public", Justification = "Disabled")]//*/
public /**/class DatabaseTests
{
}
Note that using full namespace path for SupressMessage does not mess up with your usings.
You need to set the your class access level as as internal and surpress message as #Miq did:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "xUnit1000:Test classes must be public", Justification = "Disabled")]
internal class MyClassThatIsNotATestClass
{ ... }
You can create LocalOnlyFactAttribute
public class LocalOnlyFactAttribute : FactAttribute
{
//uncomment to run on local
//const string skip = null;
//keep this to avoid slow running tests on other env
const string skip = "Disabled slow running tests.";
public override string Skip { get => skip; set => base.Skip = value; }
}
As far as I know, the simplest way to dynamically skip a whole xUnit test class at runtime is to use the TestFrameworkAttribute at the assembly level, to point to a class that implements the ITestFramework interface (or inherits from XunitTestFramework, which is simpler) and which overrides the CreateDiscoverer() method to return another class, that implements the ITestFrameworkDiscoverer interface (or inherits from XunitTestFrameworkDiscoverer, which is simpler), where you can finally override the IsValidTestClass() method, to decide whether a class should be skipped or not.
Here is some sample code:
[assembly: TestFramework("MyNamespace.Xunit.MyTestFramework", "MyAssembly")]
namespace MyNamespace.Xunit
{
public class MyTestFramework : XunitTestFramework
{
public MyTestFramework(IMessageSink messageSink)
: base(messageSink)
{
}
protected override ITestFrameworkDiscoverer CreateDiscoverer(
IAssemblyInfo assemblyInfo)
=> new MyTestFrameworkDiscoverer(
assemblyInfo,
SourceInformationProvider,
DiagnosticMessageSink);
}
public class MyTestFrameworkDiscoverer : XunitTestFrameworkDiscoverer
{
public MyTestFrameworkDiscoverer(
IAssemblyInfo assemblyInfo,
ISourceInformationProvider sourceProvider,
IMessageSink diagnosticMessageSink,
IXunitTestCollectionFactory collectionFactory = null)
: base(
assemblyInfo,
sourceProvider,
diagnosticMessageSink,
collectionFactory)
{
}
protected override bool IsValidTestClass(ITypeInfo type)
=> base.IsValidTestClass(type) &&
FilterType(type);
protected virtual bool FilterType(ITypeInfo type)
{
// Insert your custom filter conditions here.
return true;
}
}
}
Tested with xUnit 2.4.1.
We are using it in Pomelo.EntityFrameworkCore.MySql (see AssemblyInfo.cs and MySqlXunitTestFrameworkDiscoverer.cs) (a bit more complex than the sample code here).
You could achieve this through a custom ITestClassCommand.
See http://mariangemarcano.blogspot.be/2010/12/xunitnet-running-tests-testcategory.html
Here's another hack that requires minimal changes to code
using FactAttribute = System.Runtime.CompilerServices.CompilerGeneratedAttribute;
using TheoryAttribute = System.Runtime.CompilerServices.CompilerGeneratedAttribute;
Any compatible attribute can be used for the replacement.
If you also use the InlineDataAttribute then you'll need to define a replacement as I don't think there's an existing compatible attribute.
using InlineDataAttribute = DummyDataAttribute;
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
internal class DummyDataAttribute : Attribute
{
public DummyDataAttribute(params object[] data)
{
}
}
Adding a reason almost after one year after the initial question. I have a set of tests which are calling real server apis, and I would like to run then on demand. With nUnit, it has Ignore attribute : with that set, test runner will skip those tests, but I can still manually run it.
xUnit has no such feature. The nearest one is setting such a class level attribute, and comment it out when I want to run it.
Consider creating LocalOnlyFactAttribute, which can be reused across multiple test files.
public class LocalOnlyFactAttribute : FactAttribute
{
//uncomment to run on local
//const string skip = null;
//keep this to avoid slow running tests on other env
const string skip = "Disabled slow running tests.";
public override string Skip { get => skip; set => this.Skip = value; }
}
I have a unit test (nUnit). Many layers down the call stack a method will fail if it is running via a unit test.
Ideally you would use something like mocking to setup the object that this method is depending on but this is 3rd party code and I can't do that without a lot of work.
I don't want setup nUnit specific methods - there are too many levels here and its a poor way of doing unit test.
Instead what I would like to do is to add something like this deep down in the call stack
#IF DEBUG // Unit tests only included in debug build
if (IsRunningInUnitTest)
{
// Do some setup to avoid error
}
#endif
So any ideas about how to write IsRunningInUnitTest?
P.S. I am fully aware that this is not great design, but I think its better than the alternatives.
I've done this before - I had to hold my nose while I did it, but I did it. Pragmatism beats dogmatism every time. Of course, if there is a nice way you can refactor to avoid it, that would be great.
Basically I had a "UnitTestDetector" class which checked whether the NUnit framework assembly was loaded in the current AppDomain. It only needed to do this once, then cache the result. Ugly, but simple and effective.
Taking Jon's idea this is what I came up with -
using System;
using System.Reflection;
/// <summary>
/// Detect if we are running as part of a nUnit unit test.
/// This is DIRTY and should only be used if absolutely necessary
/// as its usually a sign of bad design.
/// </summary>
static class UnitTestDetector
{
private static bool _runningFromNUnit = false;
static UnitTestDetector()
{
foreach (Assembly assem in AppDomain.CurrentDomain.GetAssemblies())
{
// Can't do something like this as it will load the nUnit assembly
// if (assem == typeof(NUnit.Framework.Assert))
if (assem.FullName.ToLowerInvariant().StartsWith("nunit.framework"))
{
_runningFromNUnit = true;
break;
}
}
}
public static bool IsRunningFromNUnit
{
get { return _runningFromNUnit; }
}
}
Pipe down at the back we're all big enough boys to recognise when we're doing something we probably shouldn't ;)
Adapted from Ryan's answer. This one is for the MS unit test framework.
The reason I need this is because I show a MessageBox on errors. But my unit tests also test the error handling code, and I don't want a MessageBox to pop up when running unit tests.
/// <summary>
/// Detects if we are running inside a unit test.
/// </summary>
public static class UnitTestDetector
{
static UnitTestDetector()
{
string testAssemblyName = "Microsoft.VisualStudio.QualityTools.UnitTestFramework";
UnitTestDetector.IsInUnitTest = AppDomain.CurrentDomain.GetAssemblies()
.Any(a => a.FullName.StartsWith(testAssemblyName));
}
public static bool IsInUnitTest { get; private set; }
}
And here's a unit test for it:
[TestMethod]
public void IsInUnitTest()
{
Assert.IsTrue(UnitTestDetector.IsInUnitTest,
"Should detect that we are running inside a unit test."); // lol
}
Simplifying Ryan's solution, you can just add the following static property to any class:
public static readonly bool IsRunningFromNUnit =
AppDomain.CurrentDomain.GetAssemblies().Any(
a => a.FullName.ToLowerInvariant().StartsWith("nunit.framework"));
I use a similar approach as tallseth
This is the basic code which could be easily modified to include caching.
Another good idea would be to add a setter to IsRunningInUnitTest and call UnitTestDetector.IsRunningInUnitTest = false to your projects main entry point to avoid the code execution.
public static class UnitTestDetector
{
public static readonly HashSet<string> UnitTestAttributes = new HashSet<string>
{
"Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute",
"NUnit.Framework.TestFixtureAttribute",
};
public static bool IsRunningInUnitTest
{
get
{
foreach (var f in new StackTrace().GetFrames())
if (f.GetMethod().DeclaringType.GetCustomAttributes(false).Any(x => UnitTestAttributes.Contains(x.GetType().FullName)))
return true;
return false;
}
}
}
Maybe useful, checking current ProcessName:
public static bool UnitTestMode
{
get
{
string processName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
return processName == "VSTestHost"
|| processName.StartsWith("vstest.executionengine") //it can be vstest.executionengine.x86 or vstest.executionengine.x86.clr20
|| processName.StartsWith("QTAgent"); //QTAgent32 or QTAgent32_35
}
}
And this function should be also check by unittest:
[TestClass]
public class TestUnittestRunning
{
[TestMethod]
public void UnitTestRunningTest()
{
Assert.IsTrue(MyTools.UnitTestMode);
}
}
References:
Matthew Watson in http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/11e68468-c95e-4c43-b02b-7045a52b407e/
Somewhere in the project being tested:
public static class Startup
{
public static bool IsRunningInUnitTest { get; set; }
}
Somewhere in your unit test project:
[TestClass]
public static class AssemblyInitializer
{
[AssemblyInitialize]
public static void Initialize(TestContext context)
{
Startup.IsRunningInUnitTest = true;
}
}
Elegant, no. But straightforward and fast. AssemblyInitializer is for MS Test. I would expect other test frameworks to have equivalents.
In test mode, Assembly.GetEntryAssembly() seems to be null.
#IF DEBUG // Unit tests only included in debug build
if (Assembly.GetEntryAssembly() == null)
{
// Do some setup to avoid error
}
#endif
Note that if Assembly.GetEntryAssembly() is null, Assembly.GetExecutingAssembly() isn't.
The documentation says: The GetEntryAssembly method can return null when a managed assembly has been loaded from an unmanaged application.
Just use this:
AppDomain.CurrentDomain.IsDefaultAppDomain()
In test mode, it will return false.
I use this only for skipping logic that disables all TraceAppenders in log4net during startup when no debugger is attached. This allows unit tests to log to the Resharper results window even when running in non-debug mode.
The method that uses this function is either called on startup of the application or when beginning a test fixture.
It is similar to Ryan's post but uses LINQ, drops the System.Reflection requirement, does not cache the result, and is private to prevent (accidental) misuse.
private static bool IsNUnitRunning()
{
return AppDomain.CurrentDomain.GetAssemblies().Any(assembly => assembly.FullName.ToLowerInvariant().StartsWith("nunit.framework"));
}
Having a reference to nunit framework doesn't mean that test is actually running. For example in Unity when you activate play mode tests the nunit references are added to the project. And when you run a game the references are exist, so UnitTestDetector would not work correctly.
Instead of checking for nunit assembly we can ask nunit api to check is code under executing test now or not.
using NUnit.Framework;
// ...
if (TestContext.CurrentContext != null)
{
// nunit test detected
// Do some setup to avoid error
}
Edit:
Beware that the TestContext may be automatically generated if it's required.
I have a solution that's closer to what the original poster wanted. The issue is how to set the test flag to indicate the code is executing as part of a test. This can be implemented with 2 lines of code.
I have added an internal variable called RunningNunitTest at the top of the class. Be sure to make this an internal variable and not public. We don't want to export this variable when we build the project. Also this is how we're going to allow NUnit to set it to true.
NUnit does not have access to private variables or methods in our code. This is an easy fix. In between the using statements and the namespace add a [assembly: InternalsVisibleTo("NUnitTest")] decoration. This allows NUint access to any internal variable or method. My NUnit test project is named "NUintTest." Replace this name with the name of your NUint test Project.
That's it! Set RunningNunitTest to true in your NUnit tests.
using NetworkDeviceScanner;
[assembly: InternalsVisibleTo("NUnitTest")] // Add this decoration to your class
namespace NetworkDeviceScannerLibrary
{
public class DetectDevice
{
internal bool RunningNunitTest = false; // Add this variable to your class
public ulong TotalAddressesFound;
public ulong ScanCount;
NUnit Code
var startIp = IPAddress.Parse("191.168.1.1");
var endIp = IPAddress.Parse("192.168.1.128");
var detectDevice = new DetectDevice
{
RunningNunitTest = true
};
Assert.Throws<ArgumentOutOfRangeException>(() => detectDevice.DetectIpRange(startIp, endIp, null));
works like a charm
if (AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.FullName.ToLowerInvariant().StartsWith("nunit.framework")) != null)
{
fileName = #"C:\Users\blabla\xxx.txt";
}
else
{
var sfd = new SaveFileDialog
{ ... };
var dialogResult = sfd.ShowDialog();
if (dialogResult != DialogResult.OK)
return;
fileName = sfd.FileName;
}
.
Unit tests will skip application entry point. At least for wpf, winforms and console application main() is not being called.
If main method is called than we are in run-time, otherwise we are in unit test mode:
public static bool IsUnitTest { get; private set; } = true;
[STAThread]
public static void main()
{
IsUnitTest = false;
...
}
I was unhappy to have this problem recently. I solved it in a slightly different way. First, I was unwilling to make the assumption that nunit framework would never be loaded outside a test environment; I was particularly worried about developers running the app on their machines. So I walked the call stack instead. Second, I was able to make the assumption that test code would never be run against release binaries, so I made sure this code did not exist in a release system.
internal abstract class TestModeDetector
{
internal abstract bool RunningInUnitTest();
internal static TestModeDetector GetInstance()
{
#if DEBUG
return new DebugImplementation();
#else
return new ReleaseImplementation();
#endif
}
private class ReleaseImplementation : TestModeDetector
{
internal override bool RunningInUnitTest()
{
return false;
}
}
private class DebugImplementation : TestModeDetector
{
private Mode mode_;
internal override bool RunningInUnitTest()
{
if (mode_ == Mode.Unknown)
{
mode_ = DetectMode();
}
return mode_ == Mode.Test;
}
private Mode DetectMode()
{
return HasUnitTestInStack(new StackTrace()) ? Mode.Test : Mode.Regular;
}
private static bool HasUnitTestInStack(StackTrace callStack)
{
return GetStackFrames(callStack).SelectMany(stackFrame => stackFrame.GetMethod().GetCustomAttributes(false)).Any(NunitAttribute);
}
private static IEnumerable<StackFrame> GetStackFrames(StackTrace callStack)
{
return callStack.GetFrames() ?? new StackFrame[0];
}
private static bool NunitAttribute(object attr)
{
var type = attr.GetType();
if (type.FullName != null)
{
return type.FullName.StartsWith("nunit.framework", StringComparison.OrdinalIgnoreCase);
}
return false;
}
private enum Mode
{
Unknown,
Test,
Regular
}
Application.Current is null when running under the unit tester. At least for my WPF app using MS Unit tester. That's an easy test to make if needed. Also, something to keep in mind when using Application.Current in your code.
if (string.IsNullOrEmpty(System.Web.Hosting.HostingEnvironment.MapPath("~")))
{
// Running not as a web app (unit tests)
}
// Running as a web app
There is a really simple solution as well when you are testing a class...
Simply give the class you are testing a property like this:
// For testing purposes to avoid running certain code in unit tests.
public bool thisIsUnitTest { get; set; }
Now your unit test can set the "thisIsUnitTest" boolean to true, so in the code you want to skip, add:
if (thisIsUnitTest)
{
return;
}
Its easier and faster than inspecting the assemblies. Reminds me of Ruby On Rails where you'd look to see if you are in the TEST environment.
Considering your code is normaly run in the main (gui) thread of an windows forms application and you want it to behave different while running in a test you can check for
if (SynchronizationContext.Current == null)
{
// code running in a background thread or from within a unit test
DoSomething();
}
else
{
// code running in the main thread or any other thread where
// a SynchronizationContext has been set with
// SynchronizationContext.SetSynchronizationContext(synchronizationContext);
DoSomethingAsync();
}
I am using this for code that I want to fire and forgot in a gui application but in the unit tests I might need the computed result for an assertation and I don't want to mess with multiple threads running.
Works for MSTest. The advantage it that my code does not need to check for the testing framework itself and if I really need the async behaviour in a certain test I can set my own SynchronizationContext.
Be aware that this is not a reliable method to Determine if code is running as part of a unit test as requested by OP since code could be running inside a thread but for certain scenarios this could be a good solution (also: If I am already running from a background thread, it might not be necessary to start a new one).
I've used the following in VB in my code to check if we ae in a unit test. spifically i didn't want the test to open Word
If Not Application.ProductName.ToLower().Contains("test") then
' Do something
End If
How about using reflection and something like this:
var underTest = Assembly.GetCallingAssembly() != typeof(MainForm).Assembly;
The calling assembly will be where your test cases are and just substitute for MainForm some type that's in your code being tested.