Unit Testing Timed Removal of Dictionary Value - c#

I am writing an in-memory cache (for lack of a better term) in C#. Writing the cache was the easy part, but testing it is another...
All of my research into testing classes that use timers is to mock the timer and inject it into the class. With this, a new timer needs to be initialized for each order that is added to the cache. Passing a timer into the Add function would solve this, but classes consuming the OrderCache shouldn't be responsible for passing a timer to it.
I need to verify that
the timer has been initialized
Remove is called for the proper order after the specified duration
the order is updated in the Dictionary and no timer is created when adding the same order twice
private readonly Dictionary<int, Order> _orders;
private TimeSpan _cacheDuration;
public OrderCache(TimeSpan cacheDuration)
{
_cacheDuration = cacheDuration;
_orders = new Dictionary<int, Order>();
}
public void Add(Order order)
{
var cachedOrder = GetOrderById(order.Id);
if (cachedOrder == null)
{
_orders.Add(order.Id, order);
var timer = new Timer(_cacheDuration.TotalMilliseconds);
timer.Elapsed += (sender, args) => Remove(order.Id);
}
else
{
_orders[order.Id] = order;
}
}
public Order GetOrderById(int orderId)
{
return _orders.ContainsKey(orderId) ? _orders[orderId] : null;
}
public void Remove(int orderId)
{
if (_orders.ContainsKey(orderId))
{
_orders.Remove(orderId);
}
}

A: the timer has been initialized
Q: You should avoid White-Box Testing, because if internal implementation changed, but not behavior, interface or contract, you should rewrite test again.
A: Remove is called for the proper order after the specified duration
Q: You can write test:
[Test]
void Should_remove_...()
{
MockTimer timer = new MockTimer();
MyCache cache = new MyCache(timer);
DateTime expiredAt = DateTime.Now.Add(..);
cache.Add("key", "value", expiredAt);
timer.SetTime(expiredAt);
Assert.That(cache, Is.Empty)
}
PS: I recommend the use http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache.aspx

With that being said :):
There are only two hard things in Computer Science: cache invalidation and naming things.
-- Phil Karlton
#JonSkeet's advise is the way to go - either cleanup the cache on each poll (if happens often), or have a thread to cleanup regularly.
If you still think to preserve your approach, instead of passing in a timer into the cache, pass ITimerFactory. Then each Add call can use the factory to create a timer, and set it accordingly.
You can mock the factory to produce mock timer and set it to the proper time. which you can control for your tests.
Your test will have the form (pseudo):
var timer = new Mock<ITimer>();
var factory = new Mock<ITimerFactory>();
factory.Setup(f => f.CreateTimer()).Returns(timer.Object);
....
....
timer.Verify(t => t.SetTime(expiredAt), Times.Once());

Related

Static vs Instance in Parallel Loop which is better in terms of memory and performace

I wanted to know what is a better approach for solving the below problem.
I have a situation where I will be making a service call and db call and based on the inputs i will be doing some calculations and return some mismatch between those two.
I have the below sample snippet: If anyone could advise if making the Class static is better or the instance method is better as the call will be from Parallel.for where multiple threads will be using it at the same time.
//Sample Call ..actually will be controllig no of parallel calls using MAxDegreeofparallelism
Parallel.For(1, 10, i =>
{
SomeClass c = new SomeClass();
var res=c.SomeMethod("test", "test");
});
public class SomeClass
{
private readonly IDbRepositroy _IDbRepository =null;
private readonly IServiceRepositroy _IServiceRepositroy = null;
public SomeClass()
{
_IDbRepository = new DbRepository(); // Can do DI
_IServiceRepositroy = new ServiceRepositroy(); // Can DO DI
}
//Here Return Type is shown as string but can a new class object of errors
public List<Errors> SomeMethod(string param1,string param2)
{ var err = new List<Errors>();
var dbData = _IDbRepository.GetDbData(param1, param2);
var serviceData = _IServiceRepositroy.GetServiceData(param1, param2);
//Based on Servcie Data and DB data Calculate erros and return
//Code Logic
//Multiple Logic
return err;
}
}
In my opinion it make sense to prepare a cache providing some set of class instances and get instance from cache when required. It is better to avoid creating new class instances during execution of parallel operations because it may cause specific GC operations that may block all running threads (mostly they run in a single thread, but if they block application this is an issue). BTW: The best way to check what is going one is to use some profile tools. I prefer PerfView provided by Microsoft, since it help to diagnose problems with GC.

FakeItEasy Action parameter in UnitTest, but still execute inner Action code

I'm currently making some UnitTests for some new features I've added to our ASP.NET project (no it's not test-driving design). We use the NHibernate framework and use the UnitTest Mock-ing library FakeItEasy.
I have the following class & method which I want to test:
public class Round
{
public static Round Create(List<Company> activeCompanies, Period period,
BusinessUser user, BusinessUser systemUser,
ISession session, IEntityQuery entityQuery,
RoundProcessBuilder processBuilder)
{
var round = new Round
{
Processes = new List<Process>();
Period = period,
CreationDate = DateTime.Now,
CreatedBy = user
};
// Save the Round in the DB so we can use it's Id in the Processes:
session.Save(round);
foreach (var company in activeCompanies)
{
var companyData = session.Get<CompanyData>(company.Id);
var processResult =
roundProcessBuilder.Build(
systemUser,
new CreateRoundProcessData(company, round, companyData),
entityQuery,
session);
processResult.HandleProcess(process =>
{
// serviceBus can stay null
process.Create(systemUser, DateTime.Now, session, null);
// No need to save the session here. If something went
// wrong we don't want halve of the processes being saved
round.Processes.Add(process);
// It's all or nothing
});
}
return round;
}
}
What I mainly want to test: When I use this Round#Create method with let's say 100 active companies, it should create 100 processes, and each of those processes should contain the RoundId.
This is my UnitTest so far:
[TestFixture]
public class RoundTest
{
private BusinessUser _systemUser;
private DateTime _creationDateRound1;
private List<Company> _activeCompanies;
private RoundProcessBuilder _roundProcessBuilder;
private ISession _session;
[SetUp]
public void Setup()
{
_creationDateRound1 = new DateTime(2015, 10, 5);
_systemUser = TestHelper.CreateBusinessUser(Role.Create("systemuser", "test",
Int32.MaxValue));
_activeCompanies = new List<Company>
{
TestHelper.CreateCompany();
};
_roundProcessBuilder = A.Fake<RoundProcessBuilder>();
_session = A.Fake<ISession>();
}
[Test]
public void TestCreateRoundWithoutPreviousRound()
{
var fakeExpectedRound = Round.Create(_activeCompanies, DateTime.Now.ToPeriod(),
_systemUser, _systemUser, _session, null, _roundProcessBuilder);
var fakeExpectedRoundData = RoundProcessData.Create(TestHelper.CreateCompany(),
fakeExpectedRound, new CompanyData());
var fakeExpectedProcess = new Process(_systemUser, null, "processName", null,
fakeExpectedRoundData, "controllerName", null);
var processSuccessResult = new ProcessSuccessResult(fakeExpectedProcess);
A.CallTo(() => _roundProcessBuilder.Build(null, null, null, null))
.WithAnyArguments()
.Returns(processSuccessResult);
A.CallTo(() => processSuccessResult.HandleProcess(A<Action<Process>>.Ignored))
.Invokes((Action<Process> action) => action(fakeExpectedProcess));
var round = Round.Create(_activeCompanies, _ceationDateRound1.ToPeriod(),
_systemUser, _systemUser, _session, null, _roundProcessBuilder);
Assert.AreEqual(_activeCompanies.Count, round.Processes.Count, "Number of processes");
Assert.AreEqual(round.Period.Quarter, Math.Ceiling(_creationDateRound1.Month / 3.0m), "Quarter");
Assert.AreEqual(round.Period.Year, round.Year, "Year");
// Test if each of the processes knows the RoundId, have the proper state,
// and are assigned to the systemuser
//foreach (var process in round.Processes)
//{
// var roundProcessData = process.ProcessData as RoundProcessData;
// Assert.IsNotNull(roundProcessData, "All processes should have RoundProcessData-objects as their data-object");
// Assert.AreEqual(roundProcessData.Round.Id, round.Id, "RoundId");
// Assert.AreEqual(process.Phase.State, PhaseState.Start, "Process state should be Start");
// Assert.AreEqual(process.AssignedTo, _systemUser, "AssignedTo should be systemuser");
//}
}
... // More tests
}
My problem lies in the following code:
A.CallTo(() => processSuccessResult.HandleProcess(A<Action<Process>>.Ignored))
.Invokes((Action<Process> action) => action(fakeExpectedProcess));
It gives an "The specified object is not recognized as a fake object." error.
The reason I have this part of the code is because the process in the following part was null without it:
processResult.HandleProcess(process => // <- this was null
{
process.Create(systemUser, DateTime.Now, session, null);
round.Processes.Add(process);
});
PS: I uncommented the foreach with additional checks in my UnitTest because it most likely is pretty useless anyway when I mock the process itself.. My main test is if processes are created and added to the list based on the active companies given.
Your problem seems to be that you are trying to add "fake" logic to an object that is not in fact, a fake:
// You create this as an instance of ProcessSuccessResult:
var processSuccessResult = new ProcessSuccessResult(fakeExpectedProcess);
...then proceed to attempt to add a condition to it here:
A.CallTo(() =>
processSuccessResult
.HandleProcess(A<Action<Process>>.Ignored))
.Invokes((Action<Process> action) => action(fakeExpectedProcess));
In order to do this last bit, the variable processSuccessResult will need to be a fake instance of an interface, so that FakeItEasy can work with it, and apply the logic you want.
I'm assuming ProcessSuccessResult is a class you have access to, and are able to edit? If so, you should be able to add an interface to it, that will contain the methods you need, so you can work against that later.
Once you've defined that, you should be able to create your fake object as follows, where IProcessSuccessResult will be a fake implementation of your interface, provided by FakeItEasy:
var processSuccessResult = A.Fake<IProcessSuccessResult>();
Now you should be able to add logic to that fake object using A.CallTo(...).
Of course, this will imply that the real implementation of your class ProcessSuccessResult is not included or called via the variable processSuccessResult. If part of it needs to be, then you might try to either:
Add logic similar to it, or calls to it from the fake object using FakeItEasy's set up code (although this might get overly complicated), OR:
Add a separate variable to contain an instance of the real class (i.e. two variables fakeProcessSuccessResult and processSuccessResult, respectively), and use separate tests for testing separate aspects of your both this class, and it's usages.
I would recommend the latter, if possible.
I hope this is clear enough, and that this will be useful to you. I know it can be quite complicated sometimes, to find the optimal strategy for testing things like this.

How to return a data before method complete execution?

I have a slow and expensive method that return some data for me:
public Data GetData(){...}
I don't want to wait until this method will execute. Rather than I want to return a cached data immediately.
I have a class CachedData that contains one property Data cachedData.
So I want to create another method public CachedData GetCachedData() that will initiate a new task(call GetData inside of it) and immediately return cached data and after task will finish we will update the cache.
I need to have thread safe GetCachedData() because I will have multiple request that will call this method.
I will have a light ping "is there anything change?" each minute and if it will return true (cachedData != currentData) then I will call GetCachedData().
I'm new in C#. Please, help me to implement this method.
I'm using .net framework 4.5.2
The basic idea is clear:
You have a Data property which is wrapper around an expensive function call.
In order to have some response immediately the property holds a cached value and performs updating in the background.
No need for an event when the updater is done because you poll, for now.
That seems like a straight-forward design. At some point you may want to use events, but that can be added later.
Depending on the circumstances it may be necessary to make access to the property thread-safe. I think that if the Data cache is a simple reference and no other data is updated together with it, a lock is not necessary, but you may want to declare the reference volatile so that the reading thread does not rely on a stale cached (ha!) version. This post seems to have good links which discuss the issues.
If you will not call GetCachedData at the same time, you may not use lock. If data is null (for sure first run) we will wait long method to finish its work.
public class SlowClass
{
private static object _lock;
private static Data _cachedData;
public SlowClass()
{
_lock = new object();
}
public void GetCachedData()
{
var task = new Task(DoStuffLongRun);
task.Start();
if (_cachedData == null)
task.Wait();
}
public Data GetData()
{
if (_cachedData == null)
GetCachedData();
return _cachedData;
}
private void DoStuffLongRun()
{
lock (_lock)
{
Console.WriteLine("Locked Entered");
Thread.Sleep(5000);//Do Long Stuff
_cachedData = new Data();
}
}
}
I have tested on console application.
static void Main(string[] args)
{
var mySlow = new SlowClass();
var mySlow2 = new SlowClass();
mySlow.GetCachedData();
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
mySlow.GetData();
mySlow2.GetData();
}
mySlow.GetCachedData();
Console.Read();
}
Maybe you can use the MemoryCache class,
as explained here in MSDN

How to manage observable subscription for dependent observables?

This sample console application has 2 observables. The first one pushes numbers from 1 to 100. This observable is subscribed by the AsyncClass which runs a long running process for each number it gets. Upon completion of this new async process I want to be able to 'push' to 2 subscribers which would be doing something with this new value.
My attempts are commented in the source code below.
AsyncClass:
class AsyncClass
{
private readonly IConnectableObservable<int> _source;
private readonly IDisposable _sourceDisposeObj;
public IObservable<string> _asyncOpObservable;
public AsyncClass(IConnectableObservable<int> source)
{
_source = source;
_sourceDisposeObj = _source.Subscribe(
ProcessArguments,
ExceptionHandler,
Completed
);
_source.Connect();
}
private void Completed()
{
Console.WriteLine("Completed");
Console.ReadKey();
}
private void ExceptionHandler(Exception exp)
{
throw exp;
}
private void ProcessArguments(int evtArgs)
{
Console.WriteLine("Argument being processed with value: " + evtArgs);
//_asyncOpObservable = LongRunningOperationAsync("hello").Publish();
// not going to work either since this creates a new observable for each value from main observer
}
// http://rxwiki.wikidot.com/101samples
public IObservable<string> LongRunningOperationAsync(string param)
{
// should not be creating an observable here, rather 'pushing' values?
return Observable.Create<string>(
o => Observable.ToAsync<string, string>(DoLongRunningOperation)(param).Subscribe(o)
);
}
private string DoLongRunningOperation(string arg)
{
return "Hello";
}
}
Main:
static void Main(string[] args)
{
var source = Observable
.Range(1, 100)
.Publish();
var asyncObj = new AsyncClass(source);
var _asyncTaskSource = asyncObj._asyncOpObservable;
var ui1 = new UI1(_asyncTaskSource);
var ui2 = new UI2(_asyncTaskSource);
}
UI1 (and UI2, they're basically the same):
class UI1
{
private IConnectableObservable<string> _asyncTaskSource;
private IDisposable _taskSourceDisposable;
public UI1(IConnectableObservable<string> asyncTaskSource)
{
_asyncTaskSource = asyncTaskSource;
_asyncTaskSource.Connect();
_taskSourceDisposable = _asyncTaskSource.Subscribe(RefreshUI, HandleException, Completed);
}
private void Completed()
{
Console.WriteLine("UI1: Stream completed");
}
private void HandleException(Exception obj)
{
Console.WriteLine("Exception! "+obj.Message);
}
private void RefreshUI(string obj)
{
Console.WriteLine("UI1: UI refreshing with value "+obj);
}
}
This is my first project with Rx so let me know if I should be thinking differently. Any help would be highly appreciated!
I'm going to let you know you should be thinking differently... :) Flippancy aside, this looks like a case of bad collision between object-oriented and functional-reactive styles.
It's not clear what the requirements are around timing of the data flow and caching of results here - the use of Publish and IConnectableObservable is a little confused. I'm going to guess you want to avoid the 2 downstream subscriptions causing the processing of a value being duplicated? I'm basing some of my answer on that premise. The use of Publish() can achieve this by allowing multiple subscribers to share a subscription to a single source.
Idiomatic Rx wants you to try and keep to a functional style. In order to do this, you want to present the long running work as a function. So let's say, instead of trying to wire your AsyncClass logic directly into the Rx chain as a class, you could present it as a function like this contrived example:
async Task<int> ProcessArgument(int argument)
{
// perform your lengthy calculation - maybe in an OO style,
// maybe creating class instances and invoking methods etc.
await Task.Delay(TimeSpan.FromSeconds(1));
return argument + 1;
}
Now, you can construct a complete Rx observable chain calling this function, and through the use of Publish().RefCount() you can avoid multiple subscribers causing duplicate effort. Note how this separates concerns too - the code processing the value is simpler because the reuse is handled elsewhere.
var query = source.SelectMany(x => ProcessArgument(x).ToObservable())
.Publish().RefCount();
By creating a single chain for subscribers, the work is only started when necessary on subscription. I've used Publish().RefCount() - but if you want to ensure values aren't missed by the second and subsequent subscribers, you could use Replay (easy) or use Publish() and then Connect - but you'll want the Connect logic outside the individual subscriber's code because you just need to call it once when all subscribers have subscribed.

I need ideas to unit test this Tasked method

This is the method in question:
public void StartBatchProcessing(IFileBatch fileBatch)
{
var dataWarehouseFactsMerger = m_dataWarehouseFactsMergerFactory.Create(fileBatch);
dataWarehouseFactsMerger.Merge();
if(!m_isTaskStarted)
{
m_isTaskStarted = true;
m_lastQueuedBatchProcessingTask = new TaskFactory().StartNew(() => ProcessBatch(dataWarehouseFactsMerger));
}
else
{
m_lastQueuedBatchProcessingTask = m_lastQueuedBatchProcessingTask.ContinueWith(previous => ProcessBatch(dataWarehouseFactsMerger));
}
}
As you can see I'm using TPL to queue tasks one after the other and I would like to test that the tasks will execute in the order they arrive as soon as the previous one finishes.
The ProcessBatch method is protected so I think it could be overwritten in a derived class and be used to set some flag or something and assert that.
All ideas are welcome and appreciated.
You could create an implementation of DataWarehouseFactsMergerFactory that creates implementations of DataWarehouseFactsMerger that are capable of logging which fileBatch was entered and the start time of each task, but for the rest don't really do anything.

Categories

Resources