Is it a good or bad practice to use closures for asserting the method was called in such a way?

The method set a shim and return an Action wich both capture local mutable variable:

private static Action<bool> ShimCopy(FileInfo source, FileInfo destination)
    var wasCalled = false;
    ShimFileInfo.AllInstances.CopyToString = (info, destinationPath) =>
        Assert.AreEqual(source.FullName, info.FullName, "Copy wrong file");
        Assert.AreEqual(destination.FullName, destinationPath, "Copy to wrong destination");
        Assert.IsFalse(wasCalled, "Redundant file copy");
        wasCalled = true;
        return destination;
    return expected => Assert.AreEqual(expected, wasCalled);

So it could be used like this:

var assertWasCalled = ShimCopy(source, destination);

It looks convinient but I don't like impure funtions and here I have exactly the case with side effects and indeterministic results. But I've heard "Closures is a poor man's object"...

In addition returned action has no strict human readable signature describing parameter and function meaning. That could be solved by delegate, but delegate is an additional piece of complexity for the project.


Generally, I see no problem with using closures with unit testing, as long as the intent is clear and concise. Functional programming style can be difficult for others to grasp if they're not familiar with it. So, best practices here may vary from person to person and company to company. I use the pattern a lot for testing if my events are firing correctly.

bool eventCalled = false;
obj.PropertyChanged += (sender,args)=> 
obj.Change = true;

Assert::IsTrue(eventCalled, "PropertyChanged was not called");
  • \$\begingroup\$ And what about exposing assert as Func? I use it for encapsulation and separation purposes. \$\endgroup\$ – SerG Sep 26 '17 at 9:14
  • \$\begingroup\$ No problem there either. It's up to you how you want to fire your asserts. If using Func keeps the code clear, encapsulated, and separated, then go for it. \$\endgroup\$ – John Stritenberger Sep 26 '17 at 10:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.