I have following code that I'm trying to test using NUnit and Rhino mocks.
void _tracker_IndexChanged(object sender, IndexTrackerChangedEventArgs e)
{
// _context is initialised as
// SynchronizationContext _context = SynchronizationContext.Current;
// _tracker.Index is stubbed to return the value 100
_context.Post(o => _view.SetTrackbarValue(_tracker.Index), null);
}
In testcase I have set the expectation as
_view.Expect(v => v.SetTrackbarValue(100));
and when I verify expectation, the unit test fails randomaly with message
Test(s) failed. Rhino.Mocks.Exceptions.ExpectationViolationException :
IIndexTrackerView.SetTrackbarValue(100); Expected #1, Actual #0.
I failed identify the problem here, How do I fix it?
I usually solve problems like this by encapsulating global state with an abstract class or interface that can be instanced and mocked out. Then instead of directly accessing the global state, I inject an instance of my abstract class or interface into the code that uses it.
This lets me mock out the global behavior, and makes it so my tests don't depend on or exercise that unrelated behavior.
Here's one way you could do that.
public interface IContext
{
void Post(SendOrPostCallback d, Object state);
}
public class SynchronizationContextAdapter : IContext
{
private SynchronizationContext _context;
public SynchronizationContextAdapter(SynchronizationContext context)
{
_context = context;
}
public virtual void Post(SendOrPostCallback d, Object state)
{
_context.Post(d, state);
}
}
public class SomeClass
{
public SomeClass(IContext context)
{
_context = context;
}
void _tracker_IndexChanged(object sender, IndexTrackerChangedEventArgs e)
{
_context.Post(o => _view.SetTrackbarValue(_tracker.Index), null);
}
// ...
}
Then you can mock or stub out IContext
so you don't have to worry about threading, and can use a simple implementation that just executes the delegate.
If I wrote unit tests to mock this out, I'd also write higher level "integration" tests that didn't mock it out, but had less granular verifications.