chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
Hi,

After upgrading to TypeMock Isolator 4.2.2 many tests broke with the following exception:
TypeMock Verification: The call to log4net.ILog.InfoFormat() was made on an uninitialized field..

The tested class is indeed using a static log4net.ILog field initialized as following:
private static readonly ILog log = LogManager.GetLogger(typeof(MyClass));

In the documentation I found something I think is relevant to the error:
Automatic calling of the static constructor will not work before static field access only with method access.

So it seems it has something to do with the automatic mocking of all fields when using Natural Mocks. However, I am not really sure what the problem is. Is it possible to disable the automatic field mocking?

Thanks in advance
/Enrico
asked by megakemp (3k points)

8 Answers

0 votes
Hi Enrico,

Yes this relates to the automatic mocking of fields.

In order to turn this off you can use:
rec.DefaultBehavior.AutomaticFieldMocking = false;


However I would advise you against this. From what I see here you test is indeed making a call on an uninitialized field.
instead of turning this off how about setting an expectation for this?

In any case can you post the entire code?
I think that the test should have failed on the previous version as well (with a NullReferanceException)

:arrow: BTW the sentence from our documentation will be changed.
answered by lior (13.2k points)
0 votes
Hi Lior,

The tested class looks like this:
using log4net;

public static class MyClass
{
    private static readonly ILog log = LogManager.GetLogger(typeof(MyClass));

    public static void MyMethod()
    {
        //...code omitted...
        
        log.Info("Some log information");

        //...code omitted...
    }
}

The strange thing is that I am getting errors in older tests as well, that do not use TypeMock (instead they use NMock 2). These errors are System.NullReferenceException in some of them, and TypeMock.VerifyException ("The call to log4net.ILog.DebugFormat() was made on an uninitialized field..") in some others.

Even stranger is that these errors occur only when I run multiple tests at once. The same tests pass when I run them singularly :shock:

I am using MSTest 2008 as testing framework and I run my tests directly from within Visual Studio 2008.

Thanks in advance,
/Enrico
answered by megakemp (3k points)
0 votes
Hi Enrico,

According to what you describe it looks like the cctor for MyClass was mocked in one test leaving the log field uninitialized and then later on it was accessed resulting in an exception.

in order to fix this you can try one of the following:
  • 1) Initiate a call before all tests to some arbitrary method of the MyClass type. (this will force the cctor to be executed before any mocking which will cause the log field to be initialized properly)
    2) In the first test (of the execution) which mocks MyClass tell the isolator not to mock the cctor by using the Constructor.StaticNotMocked enumerator.
    3) Mock all calls made on the log field as well.

4) set the value of log field using the AssignStaticField API

Since you are using a mix of framework I would try to solve this by somehow forcing a correct value to the log field.

If nothing here works just let me know

:!: Mocking the cctor or any other static can cause one test to effect the others.
answered by lior (13.2k points)
0 votes
Hi Lior,

I tried to assign a valid instance to the log field, as you suggested, using
ILog logField = MyClass_Accessor.log;
ILog logMock = LogManager.GetLogger(typeof(MyClass));

using (RecordExpectations recorder = RecorderManager.StartRecording())
{
    recorder.AssignField<ILog>(ref logField, logMock);

    // ... code omitted ...
}

but i am still having the same problem (BTW, I could not find the AssignStaticField method in the API). To be more precise, the first test that runs in a batch (independently from which one) passes, while the others fail. The error is always the same, a TypeMock.VerifyException when my tested method calls a method on the log field.
As you can see, since log is a private static field, I am using the accessor class generated by Visual Studio using MSTest in order to assign a value to it.

I also tried to disable automatic field mocking altogether in all tests with:
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
    recorder.DefaultBehavior.AutomaticFieldMocking = false;

    // ... code omitted ... 
}

but that did not help either.
However in the documentation I found the following statement under Natural Mocks™ - All About Constructors:
Static constructors will always be called. To mock a static constructor, call recorder.MockStaticConstructors(); this will mock all static constructors that were called while recording

According to this my static log field should always be initialized, but it is actually getting a proper value only during the first test, while it is being mocked in the others. Infact when I run the tests singularly, they always pass.

I really appreciate any help on this issue, since it is stopping us from moving to TypeMock 4.2.2 on our build server.

Thanks in advance
/Enrico
answered by megakemp (3k points)
0 votes
Hi Enrico,

Let's take it offline. I'll send an email with instructions in order to get to the bottom of this.
answered by gilz (14.5k points)
0 votes
I dont understand the value of automatic field mocking. If you mock a field automatically but there are no expectations on it and I have code that accesses the field, wont the code blow up anyhow? This makes lazy loading in tests really difficult because the filed will never be null when mocked.

I just dont understand the value of this.
answered by juice_johnson (9.8k points)
0 votes
Yes it will blow up anyway.
The problem is that in a lot of cases people found it really confusing understanding why it got blown up. The NullReferanceException they got didnt help them to pinpoint the problem.

BTW I think that Enrico situation is exactly the reason why we added this feature. (but i might be mistaken since i havent seen the entire code)

in any case I hope to blog on this issue very soon so hopefully the reasons for this change will become clearer.
answered by lior (13.2k points)
0 votes
Hi everyone,

We solved this one in a patch, with the help of Enrico. It will be integrated into the next release of Isolator. If anyone encounters this problem, let us know.
answered by gilz (14.5k points)
...