NUnit - Unit Test - Dispose issue - c#

namespace Game.SoccerGame
[TestFixture]
public class Score_is_0_0 : SoccerGame
{
[SetUp]
public void SetUp()
{
GivenTheScoreIs(0,0);
}
[TearDown]
public void CleanUp()
{
}
[Test]
public void When_Team1_Scores()
{
WhenTeam1Scores();
Assert.That(ScoreOutput, Is.EqualTo("1:0"));
}
[Test]
public void When_Team2_Scores()
{
WhenTeam2Scores();
Assert.That(ScoreOutput, Is.EqualTo("0:1"));
}
}
Expected:
When_Team1_Scores() = 1:0
When_Team1_Scores() = 0:1
When I run the tests individually they work as expected.
The issue I am having is when I run the tests in the class all at the same time. When I do this the results are:
When_Team1_Scores() = 1:0
When_Team1_Scores() = 1:1
the ScoreOutput keeps its state after the first test and thus my second test fails
What is the best approach the kill the state in-between tests in the TearDown?
I have the object below in a separate class SoccerGame that I inherit that controls the score state
public abstract class SoccerGame : IDisposable
private SetScore currentScore = new SetScore();
protected string ScoreOutput => currentScore.ToString();
public void Dispose()
{
}
I tried to use IDisposable but it doesn't see to work or I am implementing it wrong?

When using NUnit, a single instance of the fixture is created and used for all the tests in the fixture. Because of that, any state that needs to be initialized should be taken care of in the SetUp method, which runs before each test.
You don't show the code for your method GivenTheScoreIs but it sounds like it's supposed to initialize the score. To ensure that it is working correctly, add a test that verifies the score is set (0:0).
The above should work. However, I recommend going a step further and not inheriting from SoccerGame, which is presumably the class you are testing. While inheriting a test in this way is occasionally useful, it isn't the normal or the cleanest way to do it. It's better to separate your system under test from the tests themselves.
To do that, I suggest you instantiate a new SoccerGame for each test, doing so in the SetUp method. That will eliminate any possibility of state carrying over from one test to another since each test will use a new SoccerGame.

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.

Unit Testing a method containing Environment.Exit() call within it

I have a public method say,
public void ErrorEncounter()
{
//Global Error Counter
gblErrorCount++;
//Process tremination
Environment.Exit();
}
This method terminates whenever it is called. However, it will update the Global Error Count which i'm suppose to test. Is there any way to perform Unit Testing on this method?
I'm Using NUnit Framework for Unit Testing.
This method is designed to be difficult to test!
Most obviously, because it terminates the application when called. But also because it changes a global (I assume static) variable. Both of these things prevent writing a good unit test that calls the method.
Three ways around this:
1. Eliminate the method
2. Don't test the method
3. Modify the method
Option 1. If this method only called exit, then you could simply drop it and call Exit directly. However, that would make some other method difficult to test, so this isn't really a great option.
Option 2. Sometimes a method is so simple that you can avoid testing it. Whether this is such a method depends on how gblErrorCount is used elsewhere. It would appear, however, that incrementing the count has no effect, since the process immediately exits.
Option 3. Modify the method and those methods that call it. One approach would be to use an event handling mechanism and terminate the app in the event handler. You could make this easier to test by injecting a different event handler when running tests.
IOW, this is basically a pretty untestable method. Hopefully, you are in control of the system under test and can change it.
This question contains answers that show how Environment.Exit() can be tested.
Constructor Dependency Injection
One option is to convert it into a dependency by injecting it through an interface :
interface ITerminator
{
void Exit();
}
class RealTerminator
{
void Exit()=>Environment.Exit();
}
public class MyErrorChecker
{
ITerminator _terminator;
public class MyErrorChecker(ITerminator terminator)
{
_terminator=terminator;
}
public void ErrorEncounter()
{
//Global Error Counter
gblErrorCount++;
//Process tremination
_terminator.Exit();
}
}
The test project will implement a fake terminator class that sets a flag if Exit is called:
class FakeTerminator:ITerminator
{
public bool Called{get;private set;}
public void Exit()
{
Called=true;
}
}
Mocking
Another option is to mock it by extracting the call to a virtual method that can be replaced in a mock class :
public void ErrorEncounter()
{
//Global Error Counter
gblErrorCount++;
//Process tremination
ForceExit();
}
internal virtual void ForceExit()
{
Environment.Exit();
}
The test project could create a mock error checker class:
class MockErrorChecker:MyErrorChecker
{
public bool Called{get;private set;}
public override void ForceExit()
{
Called=true;
}
}
Function injection
This option isn't included in the linked question. Pass an exit Action as a parameter to ErrorEncounter whose default will be to call Environment.Exit() :
public void ErrorEncounter(Action exitFn=null)
{
var doExit=exitFn ?? (()=>Environment.Exit());
//Global Error Counter
gblErrorCount++;
//Process tremination
doExit();
}
The test could pass its own function that sets a flag:
[Test]
public void Test_Exit_Is_Called
{
bool called;
void fakeExit() { called=true; }
thatClass.ErrorEncounter(fakeExit);
Assert.True(called);
}

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.

NUnit TestFixtureSetUp runs multiple times?

I have a basic Test setup using NUnit 2.6 and Visual NUnit in Visual Studio 2010. My problem is that when I'm running all tests it seems like the FixtureSetup method (which has the TestFixtureSetUpAttribute) is running one time for each of the tests.
I've also tried to put the Init code to the constructor, but it gives the same results.
The tests themselves reports their run time to runtime like 0.003 and 0.032 and so on.
[TestFixture]
public class MODatabaseTests
{
[TestFixtureSetUp]
public static void FixtureSetup()
{
// Perform heavy init (~1.5s)
}
[Test]
public void TestA()
{
...
}
[Test]
public void TestB()
{
...
}
}
If you add this code, you can confirm your suspicion:
private static bool initialized = false;
[TestFixtureSetUp]
public static void FixtureSetup()
{
if (initialized) Assert.Fail("fixture setup called multiple times");
initialized = true;
...
}
The test runner may calling every test individually instead of treating a TestFixture as a suite of tests.
As an aside, I would avoid static in unit tests because if you have any static variables, their state would be carried from each run (though the fixture kind of wants this) and you lose the "unit" part of unit testing.

TDD can force the creation of "fake" dependencies

I'm using a boilerplate implementation of Model-View-Presenter in an ASP.NET WebForms application. My View has two events of consequence, one that signals that the user has filled out enough fields on the domain model to initiate a duplication check, and the other is a regular Save event. My pseudo code looks like this:
public class ItemNewPresenter : PresenterBase<IItemNewView>
{
public IItemService Service { get; private set; }
public IItemNewView View { get; private set; }
public ItemNewPresenter(IItemService service, IItemNewView view)
{
Service = service;
View = view;
View.OnSave += DoItemSave;
View.OnItemIsDuplicateCheck+= DoItemIsDuplicateCheck;
}
private void DoItemIsDuplicateCheck(object sender, CheckItemDuplicateEventArgs e)
{
CheckForItemDuplication(e.Item);
}
private void CheckForItemDuplication(Item item){
if (Service.IsDuplicateItem(item))
{
View.RedirectWithNotification(BuildItemUrl(item), "This item already exists");
}
}
private void DoItemSave(object sender, SaveItemEventArgs e)
{
DoItemIsDuplicateCheck(this, e.ToItemDuplicateEventArgs());
Service.Save(e.Item);
}
}
Here's my test for ensuring that my presenter behaves properly when OnItemIsDuplicateCheck is raised from the view:
[Test]
public void presenter_checking_for_existing_item_should_call_redirect_if_found()
{
var service = new Mock<IItemService>();
var view = new Mock<IItemNewView>();
var presenter = new ItemNewPresenter (service.Object, view.Object);
var onCheckExistingHandler = view.CreateEventHandler <CheckItemDuplicateEventArgs>();
view.Object.OnExistingDenominatorCheck += onCheckExistingHandler;
var eventArgs = new CheckItemDuplicateEventArgs();
service.Setup(s => s.IsDuplicate(It.Is<CheckItemDuplicateEventArgs>(c => c.Equals(eventArgs)))).Returns(true);
onCheckExistingHandler.Raise(eventArgs);
view.Verify(v => v.RedirectWithNotification(It.IsAny<String>(), It.IsAny<string>()), Times.Once());
service.Verify();
}
For consistency, I would like to have the same duplicate check fired when the View raises the OnSave event. My question is around how I am supposed to write my test when one of the methods I want to verify (CheckForItemDuplication) is declared on the class under test. The alternative to verifying the method invocation on the SUT (bad) would be to write my save test with lots of duplicated code (setup and assertion of all my mocks would be copied from the above test) and it also makes the unit test less focused.
[Test]
public void presenter_saving_item_should_check_for_dupe_and_save_if_not_one() {
//duplicate mocks/setups/asserts from duplicate check fixture
//additional mocks/setups/asserts to test save logic
}
I think TDD would suggest pulling this private method out into a separate class that collaborates with my Presenter and would be injected via DI. But adding another dependency to my Presenter for functionality that doesn't seem worthy of being a freestanding abstraction *and*represents an internal implementation detail of my Presenter seems...well...crazy. Am I way off base here? There must be some design pattern or refactoring I can apply that would avoid the need to turn a private method into a dependency.
What I have done sometimes, when confronted with this dilemma, is to extract the function, make an internal constructor with the object as argument, AND a public constructor without. The public ctor is forwarded to the internal with a new object such as:
public class ClassThatUseInjection
{
private readonly SomeClass _injectedClass;
public ClassThatUseInjection(): this(new SomeClass()) {}
internal ClassThatUseInjection(SomeClass injectedClass)
{
_injectedClass = injectedClass;
}
}
public class SomeClass
{
public object SomeProperty { get; set; }
}
Thus, you can use the empty constructor from outside, and the other constructor for when you want to inject a stubbed argument for testpurposes. As long as the empty constructor only forwards the call without any logic of its own, you can still test it, like it has only one constructor.
I would go with testing the class as is by adding the duplicate setup code. Once that test is passing and you are confident all test cases are covered you can then refactor your test code to remove duplication.
You can move the dependencies (service and view) to private fields, then add a method to create the SUT:
private Mock<IItemService> _service;
private Mock<IItemNewView> _view;
private PresenterBase<IItemNewView> CreateSUT()
{
_service = new Mock<IItemService>();
_view = new Mock<IItemNewView>();
return new ItemNewPresenter (service.Object, view.Object);
}
(I think most people would prefer to initialize the Mock objects in the Setup method.)
Call the CreateSUT from your tests and now there is a little less duplication. Then you may want to add private method(s) for creating the event handler / raising the event as long as it is something that is being done the same or similar in more than one tests case.
Having this CreateSUT method cuts down on the amount of test code that is calling your constructor making it easier in the future if you were to add / remove / change dependencies. If you treat your test code like any other code and use the DRY principle when you see duplication it can result in more explicit, easier to read, maintainable test code. Dealing with very similar setup and test context is a common issue with unit testing and should not always change how the class being tested is/was designed.
I'll be interested if there are better answers, as I encounter this all the time.
The alternative to verifying the method invocation on the SUT (bad) would be to write my save test with lots of duplicated code (setup and assertion of all my mocks would be copied from the above test) and it also makes the unit test less focused.
I'm not sure why you feel it makes the test less focused, but in your shoes I would do exactly what it sounds like you don't want to do--have duplicated setup code to test isolated cases for the SUT. You are testing the external behavior of the SUT with the test you supplied, which seems exactly right to me.
I am personally not a fan of exposing more than is necessary from a class and/or making behavior that should be the responsibility of the SUT into a dependency just to facilitate testing. The "natural boundry" of the class's responsibility should not be violated just because you want to test it.
It is easier to unit-test the calculation of the url than to unit-test that redirection has occured.
If i understood you corretly you want to test that the mvp-s CheckForItemDuplication() redirects to a certain url by raising
the view-mock-s OnItemIsDuplicateCheck event.
private void CheckForItemDuplication(Item item)
{
if (Service.IsDuplicateItem(item))
{
View.RedirectWithNotification(BuildItemUrl(item),
"This item already exists");
}
}
In my opinion you are doing to much.
What if you rewrite your code as
internal protected GetErrorUrlForItem(Item item)
{
if (Service.IsDuplicateItem(item))
{
return BuildItemUrl(item,
"This item already exists");
}
return null;
}
private void CheckForItemDuplication(Item item)
{
var result = GetErrorUrlForItem(item);
if (result != null)
{
View.RedirectWithNotification(result);
}
}
In the unittest just test the internal method GetErrorUrlForItem(). You have to use the InternalsVisibleTo attribute to allow accessing the internal method.

Categories