How to initialize some tests and not others? - c#

Using TestInitialize(), I can initialize all the tests in the TestClass. But if I want only some tests to be initialize and not others, how can I achieve this?

Move the non-shared initialization of test data to each [TestMethod] method.
The initialization method is called once for each test, so simply move code you dont want run for all tests into the specific methods.

You can achieve this by separating them into two classes. Or, if they both use the same methods and variables, put them into subclasses that inherit from a common base class with shared methods and data.

The best way is to separate your Test Methods into different Test Classes. However If you want to have them all in one Test Class you can create different initialization methods for each test:
[TestClass]
public class TestClass
{
[TestInitialize]
public void Initialize()
{
switch (TestContext.TestName)
{
case "TestMethod1":
this.InitializeTestMethod1();
break;
case "TestMethod2":
this.InitializeTestMethod2();
break;
default:
break;
}
}
[TestMethod]
public void TestMethod1()
{
}
[TestMethod]
public void TestMethod2()
{
}
private void InitializeTestMethod1()
{
// Initialize TestMethod1
}
private void InitializeTestMethod2()
{
// Initialize TestMethod2
}
public TestContext TestContext { get; set; }
}

Related

Is there a way to mimic the function of startup.cs in unit test cases while running multiple tests together? [duplicate]

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.

Avoiding thread.sleep in code while unit testing with Moq

I have methods which have multiple thread.sleep which last for 20 seconds at times. This is a business requirement. I am trying to unit test these methods, by mocking and skipping these sleeps so that tests can run faster and doesn't actually wait for 20 seconds. Using the moq framework.
Appreciate any ideas on how to implement this.
There is probably no way to mock Thread.Sleep because it's a static method and those cannot be mocked with DynamicProxy based mocking Frameworks like moq.
One option would be to use Profiler API based tools like Microsoft Fakes (only in VS Enterprise) or Typemoq professional.
The better option is not to call Thread.Sleep directly in your business logic. What you can do instead is to introduce an Interface like this
public interface ISleepService
{
void Sleep(int ms);
}
Then create a default implementation that you use in your code:
public class SleepService: ISleepService
{
public void Sleep(int ms)
{
Thread.Sleep(ms);
}
}
Add a dependency of ISleepService to your Business Logic
public class MyBusinessLogic()
{
private ISleepService _sleepService;
public MyBusinessLogic(ISleepService sleepService)
{
_sleepService = sleepSerivce;
}
public void MyBusinessMethod()
{
// your code
_sleeService.Sleep(20000);
// more code
}
}
You can then easily mock the ISleepService in your unit tests and pass the real implementation in your production code
You can actually introduce interface for Thread.sleep methods and this you can mock while writing UTs
public interface IThreadSleep
{
void Sleep(int milliSec);
}
You can have implementation , something like this
public class ThreadSleep : IThreadSleep
{
public void Sleep(int milliSec)
{
Thread.Sleep(milliSec);
}
}
In your business class, just inject this interface and you can then mock Thread.sleep
public class Class1
{
IThreadSleep _threadSleep;
public Class1(IThreadSleep threadSleep)
{
_threadSleep = threadSleep;
}
public void SomeMethod()
{
//
_threadSleep.Sleep(100);
}
}
Hope this helps.
Don't know actual code you have but at least to have some idea. You could wrap your Thread.Sleep into the interface and then inject that one to your business handler\controller. In the actual implementation use Thread.Sleepto actually wait but within the tests mock that interface to avoid Thread.Sleep. For example:
public interface IMySleepContext
{
void Sleep(int milliseconds);
}
public class MySleepContext : IMySleepContext
{
public void Sleep(int milliseconds)
{
Thread.Sleep(milliseconds);
}
}
public class MyController
{
private readonly IMySleepContext _mySleepContext;
public MyController(IMySleepContext mySleepContext)
{
_mySleepContext = mySleepContext;
}
public void MyMethod()
{
//do something
_mySleepContext.Sleep(20000);
//do somethign
}
}
Tests:
//Arrange
MyController mc = new MyController(Mock.Of<IMySleepContext>());
//Act
mc.MyMethod();
//Assert
//do assert

TransactionAbortedException in TestInitialize

I have a base class for my unit tests which sets up a simple transaction around every test.
public class TestBase
{
TransactionScope _trans;
[TestInitialize()]
public void Init()
{
_trans = new TransactionScope();
}
[TestCleanup()]
public void Cleanup()
{
_trans.Dispose();
}
}
In one of my inheriting classes I have a bunch of work I want to do once, before any of those tests are run - this should roll back after all tests for the class are completed.
[TestClass]
public class MyTests : TestBase
{
static TransactionScope _transClass;
[ClassInitialize()]
public static void ClassInit(TestContext context)
{
_transClass = new TransactionScope();
//do some setup
}
[ClassCleanup()]
public static void ClassCleanup()
{
_transClass.Dispose();
}
[TestMethod()]
public void TestMethod()
{
//do some testing
}
}
My actual class has multiple test methods of course. The first test method passes fine, but the second throws a TransactionAbortedException when it tries to set up a new TransactioScope in TestInitialize. Could someone please explain what I have set up wrong here?
I suspect the base class TestBase may be doing something with the connection after each test.
It's best to use transactions with using statement - it eliminates problems like yours.
Also having multiple tests in a single transaction is not a good idea, this means that the tests are interdependent. This leads to hard to track issues when a test passes or fails depending if it's run in a group or on its own.
In summary, I advice against having a member field for the transaction and instead use local variables with the using statement.

Structuring TextFixtures in nUnit

Upon unit testing of some class, there is a need to test same methods for different combination of data in a class. This can be achieved by writing several TextFixtures and repeating same test methods for each one, as below.
[TextFixture]
public class WhenBuildingLongFoo
{
private Foo foo;
[Setup]
public void Creating()
{
foo = new Foo(){Height = new FooHeight(200)};
}
[Test]
public void ReturnsValidHeight()
{
Assert.AreEqual(200, foo.Height);
}
}
[TextFixture]
public class WhenBuildingShortFoo
{
private Foo foo;
[SetUp]
public void Creating()
{
foo = new Foo(){Height=newFooHeight(2);
}
[Test]
public void ReturnsValidHeight()
{
Assert.AreEqual(2, foo.Height);
}
}
What is the best way to structure such fixtures, so that method ReturnsValidHeight is written only once?
I came up with creating a public static class Utilities in a common namespace, which has this method; but could you please advise something better?
Something like create an abstract class with such method and then derive fixtures from it?
How to reuse setup among fixtures, just varying values?
Use the TestCase attribute to run the same test with different input values. That'll reduce a lot of your duplicate code. The SetUp method isn't necessary in your case either.
[TextFixture]
public class FooTests
{
[Test]
[TestCase(200)]
[TestCase(2)]
public void ReturnsValidHeight(int expectedHeight)
{
var foo = new Foo { Height = new FooHeight(expectedHeight) };
Assert.AreEqual(expectedHeight, foo.Height);
}
}
You might ckeck this library as an alternative for tests writing:
https://www.nuget.org/packages/Heleonix.Testing.NUnit/
You describe your tests in AAA or GWT styles in a way JavaScript's Jasmine or Jest do.
You tests become more readable and easier in support. With TestCase attributes you might end up with complex tests, which would be hard to understand even in few months

VS Team Test: Multiple Test Initialize Methods in Test Class

I have unit test project called “MyClassTest” in TeamTest. This project has three TestMethods. Each method needs its own test initialization steps. But when I apply TestInitializeAttribute to three initialization methods, it says the attribute should not be used more than once. Then what should be the attribute to be used to initialize each test method in Visual Studio Team Test?
Reference:
VS Team Test: .Net Unit Testing with Excel as Data Source: Adapter Failed
How to create Startup and Cleanup script for Visual Studio Test Project?
VS 2010 Load Tests Results with custom counters
How to log unit test entry and leave in MSTest
Can a unit test project load the target application's app.config file?
According to MSDN the TestInitializeAttribute:
cannot be used more than once (AllowMultiple = false), and
cannot be inherited to create your own TestInitializeAttribute.
So, my suggestion is to create the Test Initialize Methods without the TestInitialize attribute. Then in the unique TestInitialize method check which is the current executed TestMethod and call the appropriate initialize method:
[TestClass]
public class UnitTest
{
public TestContext TestContext { get; set; }
[TestInitialize]
public void Initialize()
{
switch (TestContext.TestName)
{
case "TestMethod1":
this.IntializeTestMethod1();
break;
case "TestMethod2":
this.IntializeTestMethod2();
break;
default:
break;
}
}
[TestMethod]
public void TestMethod1()
{
}
[TestMethod]
public void TestMethod2()
{
}
public void IntializeTestMethod1()
{
//Initialize Test Method 1
}
public void IntializeTestMethod2()
{
//Initialize Test Method 2
}
}
If you have three test methods, and each method has its own initialization steps, then why are you moving initialization to method which will run before every test? Only benefit I see, is that nice switch block, which adds some lines to your source file. But it gives you drawback - looking on any of these test methods, you can't really tell in which context method will be executed. So, I use initialization method to setup only basic context, which is really used by all tests in fixture.
Just move context creation to arrange part of each method.
If you have several methods, which use common context, then just extract method, which will setup context for them, and call it at the arrange part. You also can split each context setup to several steps and reuse those steps (like it done in Given-When-Then tools like Specflow).
And, of course, creating different fixtures also option.
It's a bit of an old post, but I came up with the following which seems to work OK:
First, define an attribute class:
[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public class InitialiseWithAttribute : Attribute
{
public string Id { get; private set; }
public InitialiseWithAttribute(string id)
{
Id = id;
}
}
then define an extension method in some convenient utilities class:
public static bool IsInitialisedWith(this string testName, string value)
{
bool result = false;
Type testClassType = new StackFrame(1).GetMethod().DeclaringType;
MethodInfo methodInfo = testClassType.GetMethod(testName);
if (methodInfo != null)
{
InitialiseWithAttribute initialiseWithAttribute =
methodInfo.GetCustomAttribute<InitialiseWithAttribute>(true);
if (initialiseWithAttribute != null)
{
result = initialiseWithAttribute.Id == value;
}
}
return result;
}
Now write your tests, thus:
public TestContext TestContext {get; set;}
[TestInitialize]
public void TestInitialise()
{
if (TestContext.TestName.IsInitalisedWith("DoSomethingSpecial")
{
// ... Do something special
}
else
{
// ... Do something normal
}
}
[TestMethod]
[InitialiseWith("DoSomethingSpecial")]
public void MySpecialTest()
{
// The test
}
If they need three seperate inits; then they should probably be in three separate fixtures each with their own init!
At my job we pass in an argument to TestInitialize method to determine how we want initialization to work.
public partial class CommonActions
{
public void TestInitialize(bool adminTest)
{
try
{
if (adminTest)
{
//do stuff
}
We then have a standard initialization in class definition, which defaults to false.
[TestClass]
public class ProjectTestBase : FrameworkTestBase
{
public CommonActions common { get; set; } = new CommonActions();
[TestInitialize]
public void TestInitialize() => common.TestInitialize(false);
Then in the Test cases themselves you can override the TestInitialize for any test you want.
[TestClass]
public class SetReportsInAdmin : ProjectTestBase
{
[TestInitialize]
public new void TestInitialize() => common.TestInitialize(true);
We use a Boolean to tell if Admin test, which needs to have extra overhead for setup. Take this and apply whatever variables you want in a way the gives you multiple initialization through the use of one method.

Categories