I have a way to test the code that you wrote, but it has a couple of conditions:
You need to be using Enterprise edition of Visual Studio to use
Microsoft Fakes (you may be able to get a similar concept working
with free alternative called Prig, but i have no experience with it)
You have to be targeting .net framework, not .net core.
We have to alter your code a little, like so:
public class Class3
{
private bool _initCalled = false;
public void Initialize()
{
if (!_initCalled)
{
lock (this)
{
// we need to insert an empty DummyMethod here
DummyMethod();
if (_initCalled)
return;
NoConfigInit();
_initCalled = true;
}
}
}
private void DummyMethod()
{
// This method stays empty in production code.
// It provides the hook for the unit test.
}
private void NoConfigInit()
{
}
}
Then, after generating the fakes for the library, we can write the test like so:
[TestMethod]
public void TestMethod1()
{
using (ShimsContext.Create())
{
// This is the value to capture whether the NoConfigInit was called
var initCalled = false;
// Here the DummyMethod comes into play
Namespace.Fakes.ShimClass3.AllInstances.DummyMethod =
class3 =>
typeof(Class3).GetField("_initCalled", BindingFlags.Instance | BindingFlags.NonPublic)
.SetValue(class3, true);
// This is just a hook to check whether the NoConfigInit is called.
// You may be able to test this using some other ways (e.g. asserting on state etc.)
Namespace.Fakes.ShimClass3.AllInstances.NoConfigInit = class3 => initCalled = true;
// act
new Class3().Initialize();
// assert
Assert.IsFalse(initCalled);
}
}
If you debug the test you will see that it exits in the second check.
I agree this is not an ideal way to test it, as we had to modify the original code.
Another option along the same lines is to change _initCalled
to be a property -> then Fakes can hook into setters and getters so you can avoid the DummyMethod, and simply return true on second call, like so (in the unit test):
int calls = 0;
Namespace.Fakes.ShimClass3.AllInstances.InitCalledGet = class3 => calls++ > 0;