Question
Do unit tests automatically dispose resources via garbage collection (System.IO.Stream in my case) once the test(s) have completed, or are things left open/in-use, requiring the disposing of IDisposable objects?
Context / Information
I'm currently making a unit test for a file uploader which uses a System.IO.Stream.
I've Moq'd out the HttpPostedFileBase with the InputStream of the file powered by a System.IO.MemoryStream, which all works as expected.
I currently have (altered for brevity):
[TestMethod]
public void TestUpload()
{
var stream = FunctionCreatingTheMemoryStream();
try
{
var file = new Mock<HttpPostedFileBase>();
file.Setup(f => f.FileName).Returns("test.txt");
file.Setup(f => f.InputStream).Returns(stream);
MethodThatUsesTheStream(file.Object)
// rest of test code with Assert
}
finally
{
stream.Dispose();
}
}
The question is with the MemoryStream instance that is created:
var stream = new FunctionCreatingTheMemoryStream();
Is it worthwhile placing any code after this in a try catch and then disposing of the stream in the finally statement, or with it being a unit test, will the memory stream be disposed of automatically?
So is it necessary to do this, or could it simply just be:
[TestMethod]
public void TestUpload()
{
var stream = FunctionCreatingTheMemoryStream();
var file = new Mock<HttpPostedFileBase>();
file.Setup(f => f.FileName).Returns("test.txt");
file.Setup(f => f.InputStream).Returns(stream);
MethodThatUsesTheStream(file.Object)
// rest of test code with Assert
}
The answer ultimately depends on the unit testing framework you use, but in .NET, none of the three major test frameworks (MSTest, NUnit, xUnit.net) automatically dispose of things. You have to manually ask them to do so.
You could argue that when executing a test suite, the test runner in principle launches a new process, runs all the tests, and then the process exits.
For some implementations of IDisposable, like MemoryStream, that simply means that the memory is reclaimed when the process exits. However, you can't always rely on that, because some disposable types may access out-of-process resources. You could theoretically have objects holding on to memory-mapped-files, named pipes, SQL Server connections, etc. Even if the test process exits, you may leave behind such resources. They'll probably time out sooner or later (like SQL Server connections returning to the pool), but it may slow down your system.
Furthermore, some test runners are attempting very hard to be clever these days, so they reuse one or more processes to be able to run faster, changing your test suite in and out of AppDomains.
So, in the end, unless you have something like a MemoryStream, where you're absolutely certain that it's not a big deal to leave it behind, you should deterministically dispose of your objects in your tests.
However, if you're doing Test-Driven Development, you should adopt the GOOS attitude of listening to your tests. If you write a lot of tests that involve IDisposable objects, you should consider if you can simplify your SUT's API. It depends on what you're doing, but if you write mostly managed code, you shouldn't need IDisposable much, because it's a Leaky Abstraction that leaks that the SUT depends on unmanaged resources..
In the past I have written a "Dustcart" class that implements IDisposable, and contains a collection of objects to dispose. These are disposed in the opersite order to how they are added (use a stack to implement it).
Then the test code looks like.
[Setup]
Public void Setup()
{
_dustcart = new Dustcart()
}
[TearDown]
public void TearDown ()
{
_dustcart.Dispose();
}
[TestMethod]
public void TestUpload()
{
var stream = _dustcart.DisposeOnTearDown(FunctionCreatingTheMemoryStream());
var file = new Mock<HttpPostedFileBase>();
file.Setup(f => f.FileName).Returns("test.txt");
file.Setup(f => f.InputStream).Returns(stream);
MethodThatUsesTheStream(file.Object)
// rest of test code with Assert
}
DisposeOnTearDown() is a generic method. You could put this this in a super class that all your tests inherent from, that also includes object mothers for the classes you need to mock etc.
However if you are not very careful your test code becomes harder to understand with no real benefit to the quality of the software you are testing. The tests are there to do a job and they have to be no better than is needed to do that job.
Totally agree with everyone that you need to dispose such objects. You can simplify your code a bit by using "using" statements, like this:
[TestMethod]
public void TestUpload()
{
using (var stream = FunctionCreatingTheMemoryStream())
{
var file = new Mock<HttpPostedFileBase>();
file.Setup(f => f.FileName).Returns("test.txt");
file.Setup(f => f.InputStream).Returns(stream);
MethodThatUsesTheStream(file.Object)
// rest of test code with Assert
}
}
Related
So I've been trying to write a test for mass transit using the in-memory feature. I wondered what peoples approach was to waiting for consumers to execute. In the example below a use a sleep or I've also tried a while loop, but not a fan of either, any better ideas? I basically want to check that the consumer is executed.
[Fact]
public async Task SomeTest()
{
var busControl = Bus.Factory.CreateUsingInMemory(cfg =>
{
cfg.ReceiveEndpoint("commands", ec =>
{
ec.LoadFrom(context);
});
});
var address = new Uri(bus.Address, "commands")
await sendEndpoint.Send(MyExampleCommand());
Thread.Sleep(2000);
//Check nsubstitute mock received
}
Look at the test harness features that are built into MassTransit. They should give you some good ideas of how to test them.
You can look at the harness tests to see how they should be used. Note that they work with any test framework, not just NUnit.
https://github.com/MassTransit/MassTransit/blob/develop/tests/MassTransit.Tests/Testing/ConsumerTest_Specs.cs
The Testing documentation explains how to use the test harnesses.
I'm still trying to follow the path to TDD.
Let's say I have a SunSystemBroker triggered when a file is uploaded to a Shared Folder. This broker is designed to open this file, extract records from it, try to find associated payments in another systems and finally to call a workflow!
If I want to follow TDD to develop the IBroker.Process() method how shall i do?
Note: Broker are independent assemblies inheriting from IBroker and loaded by a console app (like plugins).
This console is in charge of triggering each broker!
public interface IFileTriggeredBroker : IBroker
{
FileSystemTrigger Trigger { get; }
void Process(string file);
}
public class SunSystemPaymentBroker : IFileTriggeredBroker
{
private readonly IDbDatasourceFactory _hrdbFactory;
private readonly IExcelDatasourceFactory _xlFactory;
private readonly IK2DatasourceFactory _k2Factory;
private ILog _log;
public void Process(string file)
{
(...)
// _xlFactory.Create(file) > Extract
// _hrdbFactory.Create() > Find
// Compare Records
// _k2Factory.Create > Start
}
}
Each method are tested individually.
Thank you
Seb
Given that you say each method:
_xlFactory.Create(file);
_hrdbFactory.Create();
// Compare Records
_k2Factory.Create();
is tested individually, there is very little logic to test within Process(file).
If you use something like Moq, you can check that the calls occur:
// Arrange
const string File = "file.xlsx";
var xlFactory = new Mock<IExcelDatasourceFactory>();
var hrbdFactory = new Mock<IDbDatasourceFactory>();
var k2Factory = new Mock<IK2DatasourceFactory>();
// Act
var sut = new SunSystemPaymentBroker(xlFactory.Object, hrdbFactory.Object, k2Factory.Object); // I'm assuming you're using constructor injection
sut.ProcessFile(File);
// Assert
xlFactory.Verify(m => m.Create(File), Times.Once);
hrbdFactory.Verify(m => m.Create(), Times.Once);
k2Factory.Verify(m => m.Create(), Times.Once);
For brevity, I've done this as a single test, but breaking into 3 tests with a single "assert" (the verify calls) is more realistic. For TDD you would write each test, before wiring up that method within Process(file).
You may also want to look at having a larger, integration level tests, where you pass in concrete versions of IExcelDatasourceFactory, IK2DatasourceFactory, IDbDatasourceFactory and exercise the system in more depth.
In the book Growing Object-Oriented Software Guided by Tests, this would be defined as an Acceptance Test which would be written before work began, and failing whilst the feature is added in smaller TDD loops of functionality, which work toward the overall feature.
you have two different issues :
1) a method is designed to perform many task
Make your code SOLID, and apply the single responsibility principle.
Split with single responsibility methods : ie responsible for only one task.
2) you want to test a procedure that works by side effect (change environment), not a pure function.
So, I would advice you to split your code in pure functions calls (ie : no side effects).
Read also https://msdn.microsoft.com/en-us/library/aa730844%28v=vs.80%29.aspx
How to write unit tests for methods that use threads.
In example below how to test someMethod method ?
public class SomeClass {
private final SomeOtherClass someOtherClassInstance = IoC.getInstance(SomeOtherClass.class);
private final ExecutorService executorService = Executors.newCachedThreadPool();
public void someMethod() {
executorService.execute(new Runnable() {
#Override
public void run() {
someOtherClassInstance.someOtherMethod();
}
});
}
}
Are there any solutions in java and .net for this purpose?
Your question begs 'what is a unit test' (UT). UTs are just one form of automated tests. In this case your question implies that the code calls the OS to start a thread, so by definition, a test that tested it would not be a unit test but probably be an integration test.
Why I bother you with what seems like semantics is that understanding the intent of the test makes it so easy to write the test and structure the code. The amount of working code out there is larger than the amount of testable code out there.
So, how can this code be changed to be unit testable (I will skip the 'why bother stuff') ...
A unit test in C# tests a single type (your class) ... importantly (by definition) nothing else. So your code needs to reflect this. What you want to test is that when I call ABC it does this stuff. Something that stuff includes launching a thread. So you want to test that the method to launch a thread a called. The fundamental here is that your application requires a thread so that is what your asserting.
So how? Create a proxy, and perhaps a factory, for the thread creation. Then you can assert in a unit test that it was called and how it was treated. Sounds hard, but is really easy when you get into the habit.
BTW, Resharper makes creating a proxy for an OS types (e.g. thread). Check out the delegating members stuff in their help. If your not using Resharper you should be.
Yea I know this is not the answer you had hopped for, but believe me it is the answer you need.
I find it useful to think of tests in the categories:
Unit tests
Integration tests (or perhaps subsystem tests)
Functional test (e.g. UI/application/UAT tests)
The jMock Team has described an brilliant approach for Java in the 'jMock Cookbook: Test Multithreaded Code'. The concept of executing "thread" functionality on the same thread as the test can also be applied to C# code (see this blog post). The C# test would look like this:
[Test]
public void TestMultiThreadingCodeSynchronously()
{
// Arrange
SomeOtherClass someOtherClassMock = MockRepository.GenerateMock<SomeOtherClass>();
DeterministicTaskScheduler taskScheduler = new DeterministicTaskScheduler();
SomeClass systemUnderTest = new SomeClass(taskScheduler, someOtherClassMock);
// Act
systemUnderTest.SomeMethod();
// Now execute the new task on
// the current thread.
taskScheduler.RunTasksUntilIdle();
// Assert
someOtherClassMock.AssertWasCalled(x=>x.SomeOtherMethod());
}
Your "system under test" would look like this:
public class SomeClass
{
private readonly TaskScheduler taskScheduler;
private readonly SomeOtherClass instance;
public SomeClass(
TaskScheduler taskScheduler,
SomeOtherClass instance)
{
this.taskScheduler = taskScheduler;
this.instance = instance;
}
public void SomeMethod()
{
Task.Factory.StartNew(
instance.SomeOtherMethod,
new CancellationToken(),
TaskCreationOptions.None,
taskScheduler);
}
}
The C# solution is described in detail in this blog post.
If there is another thread, you have wait until the method has been called. You have to decide how long you should wait before considering the method wasn't called, there is no tool which can do that for you.
Of course you can mock the ExecutorService to run in the current thread and avoid the issue.
I've run into an issue with NUnit and CallContext (using C#) where NUnit is copying the anything in the existing call context that extends ILogicalThreadAffinative when a new thread is created. For example, in the following example an exception is always thrown in the newly-created thread:
[Test]
public void TestCopiedCallContext()
{
Foo f = new Foo();
f.a = 1;
CallContext.SetData("Test", f);
new Thread(new ThreadStart(delegate()
{
if (CallContext.GetData("Test") != null)
{
throw new Exception("Bad!");
}
})).Start();
Thread.Sleep(500);
}
class Foo : ILogicalThreadAffinative
{
public int a;
}
If Foo doesn't extend ILogicalThreadAffinative then the test passes. I'm using .NET 2.0 (due to other restrictions we cannot use newer versions of .NET). I've also tried using the Requires* attributes available in the latest version of NUnit but with no success. Does anyone know how to turn this behavior off?
I dont beleive that you can do what you are attempting to do. One person has suggested putting the code into an assembly where the test runner has access to it.
There is a blog post that you probably know about, that describes what the issue is.
Unit testing code that does multithreading can be challenging and I tend to isolate threads and wrap static objects.
If it were me, I think that I would try to isolate CallContext.SetData and CallContext.GetData by wrapping call context in a class CallContextWrapper : ICallContextWrapper.
The I would test that my code uses contextWrapper.SetData("Test", f) and be done with it;
I would trust that whoever wrote CallContext tested it's ability to take in some data and transfer it to a new thread. IMO CallContext is framework code that should have already been tested so you just need to isolate your code's dependency on CallContext.
I'm currently building a class using TDD. The class is responsible for waiting for a specific window to become active, and then firing some method.
I'm using the AutoIt COM library (for more information about AutoIt look here) since the behavior I want is actually a single method in AutoIt.
The code is pretty much as the following:
public class WindowMonitor
{
private readonly IAutoItX3 _autoItLib;
public WindowMonitor(IAutoItX3 autoItLib)
{
_autoItLib = autoItLib;
}
public void Run() // indefinitely
{
while(true)
{
_autoItLib.WinWaitActive("Open File", "", 0);
// Do stuff now that the window named "Open File" is finally active.
}
}
}
As you can see the AutoIt COM library implements an interface wich I can mock (Using NUnit and Rhino Mocks):
[TestFixture]
public class When_running_the_monitor
{
WindowMonitor subject;
IAutoItX3 mockAutoItLibrary;
AutoResetEvent continueWinWaitActive;
AutoResetEvent winWaitActiveIsCalled;
[SetUp]
public void Setup()
{
// Arrange
mockAutoItLibrary = MockRepository.GenerateStub<IAutoItX3>();
mockAutoItLib.Stub(m => m.WinWaitActive("", "", 0))
.IgnoreArguments()
.Do((Func<string, string, int, int>) ((a, b, c) =>
{
winWaitActiveIsCalled.Set();
continueWinWaitActive.WaitOne();
return 1;
}));
subject = new Subject(mockAutoItLibrary)
// Act
new Thread(new ThreadStart(subject.Run)).Start();
winWaitActiveIsCalled.WaitOne();
}
// Assert
[Test]
[Timeout(1000)]
public void should_call_winWaitActive()
{
mockAutoItLib.AssertWasCalled(m => m.WinWaitActive("Bestand selecteren", "", 0));
}
[Test]
[Timeout(1000)]
public void ensure_that_nothing_is_done_while_window_is_not_active_yet()
{
// When you do an "AssertWasCalled" for the actions when the window becomes active, put an equivalent "AssertWasNotCalled" here.
}
}
The problem is, the first test keeps timing out. I have already found out that when the stub "WinWaitActive" is called, it blocks (as intended, on the seperate thread), and when the "AssertWasCalled" is called after that, execution never returns.
I'm at a loss how to proceed, and I couldn't find any examples of mocking out a blocking call.
So in conclusion:
Is there a way to mock a blocking call without making the tests timeout?
(P.S. I'm less interested in changing the design (i.e. "Don't use a blocking call") since it may be possible to do that here, but I'm sure there are cases where it's a lot harder to change the design, and I'm interested in the more general solution. But if it's simply impossible to mock blocking calls, suggestions like that are more that welcome!)
Not sure if I understand the problem.
Your code is just calling a method on the mock (WinWaitActive). Of course, it can't proceed before the call returns. This is in the nature of the programming language and nothing you need to test.
So if you test that WinWaitActive gets called, your test is done. You could test if WinWaitActive gets called before anything else, but this requires ordered expectations, which requires the old style rhino mocks syntax and is usually not worth to do.
mockAutoItLibrary = MockRepository.GenerateStub<IAutoItX3>();
subject = new Subject(mockAutoItLibrary)
subject.Run()
mockAutoItLib.AssertWasCalled(m => m.WinWaitActive("Open File", "", 0));
You don't do anything else then calling a method ... so there isn't anything else to test.
Edit: exit the infinite loop
You could make it exit the infinite loop by throwing an exception from the mocks. This is not very nice, but it avoids having all this multi-threading stuff in the unit test.
mockAutoItLibrary = MockRepository.GenerateStub<IAutoItX3>();
// make loop throw an exception on second call
// to exit the infinite loop
mockAutoItLib
.Stub(m => m.WinWaitActive(
Arg<string>.Is.Anything,
Arg<string>.Is.Anything,
Arg<int>.Is.Anything));
.Repeat.Once();
mockAutoItLib
.Stub(m => m.WinWaitActive(
Arg<string>.Is.Anything,
Arg<string>.Is.Anything,
Arg<int>.Is.Anything));
.Throw(new StopInfiniteLoopException());
subject = new Subject(mockAutoItLibrary)
try
{
subject.Run()
}
catch(StopInfiniteLoopException)
{} // expected exception thrown by mock
mockAutoItLib.AssertWasCalled(m => m.WinWaitActive("Open File", "", 0));
Your Test only contains a call to the mocked method. Therefore it tests only your mock instead of any real code, which is an odd thing to do. We might need a bit more context to understand the problem.
Use Thread.Sleep() instead of AutoResetEvents: Since you are mocking the COM object that does the blocking window-active check, you can just wait for some time to mimick the behavior, and then make sure that the window is indeed active by making it active programmatically. How you block should not be important in the test, only that you block for some significant time.
Although from your code it is not clear how winWaitActiveIsCancelled and continueWinWaitActive contribute, I suspect they should be left out of the WinWaitActive mock. Replace them with a Thread.Sleep(500).