I'm trying to write a C# unit test with VS 2008's built-in unit testing framework and the method I'm testing calls Environment.Exit(0). When I call this method in my unit test, my unit test is Aborted. The method should indeed be calling Exit, and I want a way to test that it does, and also to test the exit code that it uses. How might I do this? I looked at Microsoft.VisualStudio.TestTools.UnitTesting Namespace but didn't see anything that looked relevant.
[TestMethod]
[DeploymentItem("myprog.exe")]
public void MyProgTest()
{
// Want to ensure this Exit's with code 0:
MyProg_Accessor.myMethod();
}
Meanwhile, here's the gist of the code that I want to test:
static void myMethod()
{
Environment.Exit(0);
}
Edit: here's the solution I used in my test method, thanks to RichardOD:
Process proc;
try
{
proc = Process.Start(path, myArgs);
}
catch (System.ComponentModel.Win32Exception ex)
{
proc = null;
Assert.Fail(ex.Message);
}
Assert.IsNotNull(proc);
proc.WaitForExit(10000);
Assert.IsTrue(proc.HasExited);
Assert.AreEqual(code, proc.ExitCode);
You'll need to create a wrapper for the Environment class, then use the wrapper in your code. For your unit tests, inject a mock version of the wrapper. The following example uses RhinoMocks to verify that the method calls the wrapper with the expected argument.
public class EnvironmentWrapper
{
public virtual void Exit( int code )
{
Environment.Exit( code );
}
}
public class MyClass
{
private EnvironmentWrapper Environment { get; set; }
public MyClass() : this( null ) { }
public MyClass( EnvironmentWrapper wrapper )
{
this.Environment = wrapper ?? new EnvironmentWrapper();
}
public void MyMethod( int code )
{
this.Environment.Exit( code )
}
}
[TestMethod]
public void MyMethodTest()
{
var mockWrapper = MockRepository.GenerateMock<EnvironmentWrapper>();
int expectedCode = 5;
mockWrapper.Expect( m => m.Exit( expectedCode ) );
var myClass = new MyClass( mockWrapper );
myclass.MyMethod( expectedCode );
mockWrapper.VerifyAllExpectations()
}
This sounds like an incredibly bad idea. Environment.Exit(0), will obviously do as prescribed, hence why your unit testings are breaking.
If you really want to still test this you can by launching a seperate process and checking the return code- have a look at wrapping it up in Process.Start.
I guess another option is factoring this code out and injecting a test spy, or using a mock object to verify correct behaviour.
Perhaps you can do something with Typemock Isolator- I believe this lets you mock static methods.
You won't be able to test this - Environment.Exit kills the application completely. This means that any AppDomain that uses this code will be unloaded completely, whether it is your production application or the unit testing framework.
Your only option here would be to mock the Environment class with a fakie Exit method.
You can add an argument to your method to pass it a fake environment where the exit() method won't exit.
You can this parametrized method extracted from the method called from your application, and unit test the extracted function. That way, you won't have to modify your app.
The only thing that comes to my mind is something along:
static void myMethod()
{
DoEnvironmentExit(0);
}
static void DoEnvironentExit(int code)
{
#if defined TEST_SOLUTION
SomeMockingFunction(code);
#else
Environment.Exit(code);
#endif
}
Related
This question already has answers here:
xUnit.net: Global setup + teardown?
(6 answers)
Closed 2 years ago.
I am trying to test some code that uses a static class. The static class has a initialization method which can be called only once and throws exception if called second time. I have multiple test cases which tests the code that need to access the static class. In the code the initialization is done in startup.cs. How do I do something similar for test cases. I am using x-unit for unit testing.
public static class UniqueId
{
public static void Initialize()
{
if (_generator != null)
throw new Exception("Already initialized.");
_generator = new IdGenerator();
}
private static IdGenerator _generator = null;
public static BigId NextId()
{
if (_generator == null)
throw new Exception("Not initialized.");
return _generator.NextId();
}
}
Code that I want to test:
public string GenerateId
{
return UniqueId.NextId().ToString()
}
In your specific case, you need to set your class to implement the IDisposible and just call Dispose() when you want to destroy it.
Here a example:
namespace Prime.UnitTests.Services
{
[TestFixture]
public class YourClassTest
{
[SetUp]
public void SetUp()
{
//some configs...
}
[Test]
public void Test_size_String_1()
{
UniqueId.Initialize();
Assert.IsFalse(UniqueId.NextId().ToString() == 10); // quick example...
UniqueId.Dispose();
}
[Test]
public void Test_size_String_2XPTO()
{
UniqueId.Initialize();
Assert.IsFalse(UniqueId.NextId().ToString() == 115); // quick example...
UniqueId.Dispose();
}
}
}
public static class UniqueId : IDisposable
{
public static void Initialize()
{
if (_generator != null)
throw new Exception("Already initialized.");
_generator = new IdGenerator();
}
private static IdGenerator _generator = null;
public static BigId NextId()
{
if (_generator == null)
throw new Exception("Not initialized.");
return c.NextId();
}
public void Dispose()
{
_generator?.Dispose(); //Depends of the context of your IdGenerator
//or
_generator == null;
}
}
Assuming I understood, in MSTest, look into [TestInitialize], [ClassInitialize] (likely what you need) and see if either works for your use case for a "startup" function
[TestInitialize]
runs before all your unit tests (each)
[ClassInitialize]
runs once, the only official doc I can find these days is older...
ClassInitializeAttribute Class
Identifies a method that contains code that must be used before any of
the tests in the test class have run and to allocate resources to be
used by the test class. This class cannot be inherited.
Remarks
When run in a load test, the method marked with this attribute
will run once, and any initialization operations it performs will
apply to the entire test. If you need to do initialization operations
once for every virtual user iteration in the test, use the
TestInitializeAttribute.
The order that methods will be run is:
Methods marked with the AssemblyInitializeAttribute.
Methods marked with the ClassInitializeAttribute.
Methods marked with the TestInitializeAttribute.
Methods marked with the TestMethodAttribute.
Only one method in a class may be decorated with this attribute.
Important
This attribute should not be used on ASP.NET unit tests, that is, any
test with [HostType("ASP.NET")] attribute. Because of the stateless
nature of IIS and ASP.NET, a method decorated with this attribute may
be called more than once per test run.
Hth
It depends on which test framework you're using.
EDIT: I see now that you're using xUnit, but I'll leave the entire answer in case it's helpful to someone else.
xUnit
You can check this answer, which talks about how to create a global setup/teardown for a set of tests. To sum up that answer, if you create a constructor for your unit test class in Xunit, that method will be called before each test method. It also states:
A more optimized version would use the IClassFixture interface to
ensure that the global initialization/teardown functionality is only
called once. For this version, you don't extends a base class from
your test class but implement the IClassFixture interface where T
refers to your fixture class:
using Xunit;
public class TestsFixture : IDisposable {
public TestsFixture ()
{
// Do "global" initialization here; Only called once.
}
public void Dispose()
{
// Do "global" teardown here; Only called once.
} }
public class DummyTests : IClassFixture<TestsFixture> {
public DummyTests(TestsFixture data)
{
}
}
This will result in the constructor of TestsFixture only being run
once for every class under test. It thus depends on what you want
exactly to choose between the two methods.
If you're using NUnit it already has a OneTimeSetUp attribute you can use (docs here), like this:
[TestFixture]
public class MyTestFixture
{
[OneTimeSetUp]
public void OneTimeSetUp()
{
// Initialize things here; only called once
}
}
If you're using something other than xUnit and NUnit, check the documentation for the framework you use, and look for a one-time setup.
In Nunit I try to test a method. I prepared the same input as in production code, but still method which do my work doesn't call properly. Tried to mock it, with no effect at this moment.
I was told that moq is the answer and it won't be easy, but send me a "Similar" question from this forum. below is try of all that I could. all found in that topic was implemented, but service is still not called properly. Checked if in normal case it would work (program.cs) and there function is called, and works as it should.
public class Helper
{
public string a;
public string b;
public Helper(string aa, string bb)
{
a = aa;
b = bb; //here is some transformation, but I checked it, and it's working properly
}
}
public class Service
{
public static string NotWorkingFunction(Helper o)
{
InternallService w = ThatPrivateFunctionWorks(o);
return ThatPrivateFunctionDont(w);
}
private InternallService ThatPrivateFunctionWorks(Helper o)
{
return DLL_external.SomeInternalService(o); //call was ok in both program, and in NUnit
}
ThatPrivateFunctionDont(InternallService w)
{
return DLL_external.CallingServiceFarAwayFromDLL(w); //this one works if is in part of program, but does not from NUnit. checks if have permission from Windows Credentials, then do a work. Error here from NUnit is that he cannot even call this function!
}
}
public class InternallService
{
public string smth;
public InternallService(Helper o)
{
smth = o.a;
}
}
public class DLL_external
{
public InternallService SomeInternalService(Helper o)
{
InternallService p = new InternallService(o);
return p; //prepare service for function. does not need to connect. output also is checked n another way, and is ok.
}
public InternallService CallingServiceFarAwayFromDLL(InternallService o)
{
return o; //here it connects to the service (don't know how, which protocol etc. works if run under program.cs)
}
}
in Nunit
public class Test
{
[Test]
public void Tester()
{
Mock<Helper> MockedObject = new Mock<Helper>("a", "B"); //Mocking an object
Mock<Service> MockedService = new Mock<Service>(MockBehavior.Strict);
var Helper = new Helper("a", "B");
Service.NotWorkingFunction(MockedObject.Object); //still does not work properly. cannot call service inside the function (But very similar thing Can, but in Program.cs)
MockedService.Object.NotWorkingFunction(MockedObject.Object);//service does not call
MockedService.Setup(p => p.NotWorkingFunction(MockedObject.Object)); //found at Stack overflow, but still function is not called
//of course all uncompiling things are commented in mine code
}
}
Expected to work. but still don't know how call it to test from NUnit. Maybe I am wrong with tool, which I use.
The idea of unit testing is that you test individual units of code rather than the whole system. Integration testing is where you test the whole system. You should test each public interface of each class individually. If that class has dependencies that you want to exclude from the test, you can create mocks of those dependencies: these are fake objects that are called instead of calling your actual code.
For example, to test the function that you say is not working you write a test that calls that function, not a test that goes through the rest of the code to hopefully call that function. You need to set up the data the function being tested needs, either directly or with mock objects. So tests for Dll_External might start like this:
[TestFixture]
public class Dll_External_Tests
{
[Test]
public void ShouldReturnAnInternalServiceFromCallingServiceFarAwayFromDLL()
{
// setup
Helper helper = new Helper("a", "B");
InternallService internalService = new InternallService(helper);
DLL_external dLL_external = new DLL_external();
// act
var result = dLL_external.CallingServiceFarAwayFromDLL(internalService);
// assert
Assert.IsNotNull(result);
Assert.IsTrue(result is InternallService);
// add more assertions for what you expect the result to be
}
}
You will see this test does not use Service at all - it is only testing DLL_External and only creates the objects it needs to be able to do that.
Incidentally, the code you have shown won't compile: you need an object to call a method on. You can only call static methods directly on the class like ClassName.StaticMethod(). Also, it can be a bit confusing if your objects have the same name as the class, convention is that class names start with a capital letter and instances (objects) start with a lower case letter.
I have a console application. In release environment, it works perfectly at this time. When in IDE debug environment, I don't want the console window close, so I added this function, and calling it in the very end of my program.
[Conditional("DEBUG")]
public static void DebugWaitAKey(string message = "Press any key")
{
Console.WriteLine(message);
Console.ReadKey();
}
It works well for me, when I debug my program. But with unit testing, it still wait for a key before exiting!
The work-around is only unit-testing release edition of my program, or test other functions. But I do want something can identify current session is under unit testing, and use that flag in this function.
I believe this should answer your question. I took a class from there and adapted it to your situation.
/// <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; }
}
Then I added a line to your method which if it is running a test it will not hit the Console.ReadKey();
[Conditional("DEBUG")]
public static void DebugWaitAKey(string message = "Press any key")
{
Console.WriteLine(message);
if(!UnitTestDetector.IsInUnitTest)
Console.ReadKey();
}
Note: This would be considered a hack and would not be considered a best practice.
EDIT:
I also created a sample project on github to demonstrate this code. https://github.com/jeffweiler8770/UnitTest
The simple way if your test runs from a dedicated UnitTest project : use a flag in AppSettings...
I would not investigate around patterns for such a purpose, i would run the test in a dedicated UnitTest project with its own configuration.
If you need to collect data maybe should you simply use traces (they can be customized from your .config file)... ?
Hope this helps...
Rather than looking for whether the program was compiled in debug mode, you can look at whether a debugger is attached:
if (Debugger.IsAttached)
{
Console.WriteLine(message);
Console.ReadKey();
}
Note this will only detect if you start with F5 from Visual Studio, not Ctrl-F5 (i.e. Start with Debugging only)
I used a variation of Jeff's UnitTestDetector. I did not want to check the unit test assembly and wanted to control which unit tests would consider this or not.
So I created a simple class with IsInUnitTest defaulting to false.
Then in the unit test classes where I wanted the conditional code to run I added TestInitializer and TestCleanup where I set the bool accordingly.
Then in my regular code I can use UnitTestDetector.IsInUnitTest
Simple UnitTestDetector class:
/// <summary>
/// Detects if we are running inside a unit test.
/// </summary>
public static class UnitTestDetector
{
static private bool _isInUnitTest = false;
public static bool IsInUnitTest
{
get { return _isInUnitTest; }
set { _isInUnitTest = value; }
}
}
Unit Test to Test this stuff:
[TestClass]
public class UnitTestDetectorTest_WithoutIsInUnitTest
{
[TestMethod]
public void IsInUnitTest_WithoutUnitTestAttribute_False()
{
bool expected = false;
bool actual = UnitTestDetector.IsInUnitTest;
Assert.AreEqual(expected, actual);
}
}
[TestClass]
public class UnitTestDetectorTest_WithIsInUnitTest
{
[TestInitialize()]
public void Initialize()
{
UnitTestDetector.IsInUnitTest = true;
}
[TestCleanup()]
public void Cleanup()
{
UnitTestDetector.IsInUnitTest = false;
}
[TestMethod]
public void IsInUnitTest_WithUnitTestAttribute_True()
{
bool expected = true;
bool actual = UnitTestDetector.IsInUnitTest;
Assert.AreEqual(expected, actual);
}
}
Condition in Code:
if (UnitTestDetector.IsInUnitTest)
return "Hey I'm in the unit test :)";
I know this is old but I really don't like many of these answers, especially anything that hard codes an assembly name or version.
This works well, as long as the class you are testing is not Sealed. It's pretty simple:
Add this class variable to the class you are testing:
protected Boolean IsInUnitTestMode = false;
We default it to false so in production it will always be false.
Add something like this wrapper to your test class
class ProfileTest : Profiles
{
public ProfileTest() : base()
{
IsInUnitTestMode = true;
}
}
In this example Profiles is the class we are testing, ProfileTest is a wrapper class in the test project's namespace. It will never be deployed. The test class uses this to create an instance of the class to be tested:
ProfileTest profiles = new ProfileTest();
As opposed to this:
private Profiles profiles = new Profiles();
The we can use it something like this:
private string ProfilePath
{
get
{
if (IsInUnitTestMode)
return SafeStorage.EnsureFolderExists(Path.Combine(SafeStorage.UserPath, UNITTESTFOLDERNAME)).FullName;
else
return SafeStorage.EnsureFolderExists(Path.Combine(SafeStorage.UserPath, PROFILEFOLDERNAME)).FullName;
}
}
As I said, this won't work with sealed classes, nor will it work well with static ones. With that said the number of times I actually choose to test for the unit test condition is quite rare. This works extremely well for me.
In visual studio 2012+, I am using Shims to allow the testing of legacy code without accessing the database. I am using the MSTest framework.
I am trying to avoid code duplication of setting up the shims multiple times; I have instead set up a helper method (e.g. below, BuildShim()) to do so. The idea is that by having the ShimObject built in the helper method, I can have it available for each of the Test methods in my test class.
In the constructor for the test class, I initialize a _idisposable = ShimsContext.Create() (which actually returns an IDisposable). In the methods, I have try {} and finally { _idisoposable.Close() };
Microsoft explicitly advises (see http://msdn.microsoft.com/en-us/library/hh549176.aspx ) using a ShimContext like this, however:
using (ShimsContext.Create()){
...
}
Questions:
Is it bad that I'm not doing it the Microsoft way? If I do it the Microsoft way, how can I avoid duplicating Shim setup code? Or it okay to put the ShimsContext initialization in the constructor and disposal in the finally {} blocks as long as I know what I'm getting into? (e.g. it might be bad if I were using ShimObject.AllInstances type methods, since I could accidentally affect a property in one place and inadvertently affect it elsewhere.)
Is there anything wrong creating the ShimsContext in the test constructor and disposing the _shimcontextDisposal in the finally block like this instead?
What happens if I don't dispose of ShimsContext? Will my computer blow up, figuratively? (e.g. will the shims never be unloaded and I would start to get weird behavior if I actually run the app?)
Example code below.
[TestClass()]
public class Tests {
//Variable to store ShimsContext idisposable. Note that we're not holding the ShimsContext,
//but rather the IDisposable object returned by the ShimsContext.Create() method
private IDisposable _shimscontextDisposable;
//Test class constructor
public Tests(){
_shimscontextDisposable = ShimsContext.Create();
}
//Test method
[TestMethod()]
public TestMethod1(){
try {
//Call the helper method below to get the shim
ShimObject shim = this.GetShimObject();
DataObject data = shim.Instance;
//... do something in test method 1
}
finally {
_shimscontextDisposable.Dispose();
}
}
//Test method 2
[TestMethod()]
public TestMethod2(){
try {
//Call the helper method below to get the shim
ShimObject shim = this.GetShimObject();
DataObject data = shim.Instance;
//... do something in test method 2
}
finally {
_shimscontextDisposable.Dispose();
}
}
//Reusable method to Build shims across methods, avoid duplicating shim setup
public ShimObject BuildShim(){
ShimObject shim = new ShimObject();
shim.TitleGet = () => { return "title"; };
shim.UrlGet = () => { return new Uri("http://www.google.com"); };
return shim;
}
For MSTest Unit Tests it is best practice not to use a constructor. Instead use the ClassInitialize or TestInitialize attribute methods, followed by the TestCleanup or ClassCleanup attribute methods.
For your case, you would set your IDisposable object in the Initialize and dispose of it in the Cleanup.
http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.classinitializeattribute.aspx
namespace TestNamespace
{
[TestClass]
public class DivideClassTest
{
[ClassInitialize]
public static void ClassInit(TestContext context)
{
}
[TestInitialize]
public void Initialize()
{
}
[TestCleanup]
public void Cleanup()
{
}
[ClassCleanup]
public static void ClassCleanup()
{
}
}
}
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.