TypeInitializationException / forcing all static c'tors to run on startup

  • Thread starter Thread starter Zytan
  • Start date Start date
Z

Zytan

I just got a TypeInitializationException exception. Why it is a
common cause for this?

The InnerException is System.FormatException, although I don't see
anything requesting something to be formatted.

I'm trying to invoke the use of a class, to force its static c'tor to
run, which will run its unit test. Is there a good way to force all
class's static c'tors to be run on startup?

Zytan
 
Is there a good way to force all
class's static c'tors to be run on startup?

No simple way. You could perhaps have a dummy static method (NOP, no
in-lining) marked with a known bespoke attribute; use reflection to
scan for this over all classes and invoke? This would (under C# rules;
the CLR actually supports more complex loading strategies) force the
static ctor (if one) to execute... Or create and instance of the class
if default ctors are available... but nothing simple.

Of course, you could simple list the necessary dummy static methods in
the top of Program.cs / global.asax - would be more efficient at
runtime, but higher maintenance.

Marc
 
Zytan said:
I just got a TypeInitializationException exception. Why it is a
common cause for this?

The InnerException is System.FormatException, although I don't see
anything requesting something to be formatted.

I'd have a look at the stack traces carefully - they should show which
class is involved.
I'm trying to invoke the use of a class, to force its static c'tor to
run, which will run its unit test. Is there a good way to force all
class's static c'tors to be run on startup?

Well, you can use Assembly.GetTypes() to get all the types in the
assembly, then use Type.TypeInitializer to get a ConstructorInfo which
you can then Invoke.

However, that will force any type initializers which have already run
to be run again, which could be dangerous depending on what they do!

As a side issue, I'm not sure that making static constructors run unit
tests is a good idea. I personally put them in a separate assembly and
run them with NUnit...
 
I just got a TypeInitializationException exception. Why it is a
I'd have a look at the stack traces carefully - they should show which
class is involved.

Looking in the stack trace of InnerException, I found this was the
problem:

string s = SomeMethod(); // can return null or "", or any string.
int x = int.Parse("0"+s);

Where "0"+s should work if s is null or "" or a non-empty string.
Commenting out this code removed the exception. What is wrong witt
that code? It runs fine elsewhere.

Zytan
 
As a side issue, I'm not sure that making static constructors run unit
tests is a good idea. I personally put them in a separate assembly and
run them with NUnit...

Well, I don't want anything overly complex. NUnit doesn't really even
say what it is (how its implemented). I have to download it to find
out. I'd be nice if it were explained a little better on the
webpage. My projects are small at the moment, so maybe I'll look into
NUnit later when I can justify that time, since I can only assume it
is rather complex if they can't give a quick explanation right away.

Thanks,

Zytan
 
Zytan said:
Looking in the stack trace of InnerException, I found this was the
problem:

string s = SomeMethod(); // can return null or "", or any string.
int x = int.Parse("0"+s);

Where "0"+s should work if s is null or "" or a non-empty string.
Commenting out this code removed the exception. What is wrong witt
that code? It runs fine elsewhere.

Well, if it returns "foo" then you'll be trying to parse "0foo" which
will indeed throw an exception.

This looks like odd code to be running in a static constructor
though...
 
Zytan said:
Well, I don't want anything overly complex. NUnit doesn't really even
say what it is (how its implemented). I have to download it to find
out. I'd be nice if it were explained a little better on the
webpage. My projects are small at the moment, so maybe I'll look into
NUnit later when I can justify that time, since I can only assume it
is rather complex if they can't give a quick explanation right away.

No, NUnit is anything but complex.

I strongly recommend that you download TestDriven.NET
(www.testdriven.net) and give it a try.

It's *definitely* worth doing unit testing properly instead of in an
ad hoc manner where you can't easily run all tests, get all results
etc.
 
string s = SomeMethod(); // can return null or "", or any string.
Well, if it returns "foo" then you'll be trying to parse "0foo" which
will indeed throw an exception.

Yes, that's true. So I need to catch this. Duh.
This looks like odd code to be running in a static constructor
though...

It's code in a method called by a method, called by a method, etc.,
that the unit testing method calls, which is invoked by the static
c'tor. The unit testing hopefully tests everything the class can do.

What I don't get is: Why, when the static c'tor is invoked, why can't
I step through the code?

NOW I GET IT, this code is being run and it's failing because
int.Parse() is throwing the exception. I thought the code wasn't
being run, and it was a type initialization failure (something that
happens before code is run, which I thought must happen a the start of
any function for all local vars or something). But, it IS a type
initialization failure, the type is the class. And the whole unit
testing and all my code is being run all in one go, without option to
step through, which tricked me into believing it wasn't being run, and
so I had to resort to strange ideas in order to explain what was
happening.

OMG.

Why can't it just report the exception at the int.Parse() line?
Strange.

Haha, what a bug.

Thanks again!

Zytan
 
What I don't get is: Why, when the static c'tor is invoked, why can't
I step through the code?

This only works if I F9 on the static c'tor itself. It won't step
into it when it is invoked automatically.
Why can't it just report the exception at the int.Parse() line?

If you are stepping through the static c'tor execution, via the method
above, when an exception it thrown that is not handled, the exception
thrown is *still* not reported on the spot. It gets tucked deep away
as the InnerException of the TypeInitializationException for the
static 'ctor. <sigh>

So, yeah, Jon, you are right -- static c'tor are NOT the best place to
run unit tests.

Now. What's a better place other than using NUnit? Like for a really
small project? (no project is too small for unit testing.)

Zytan
 
Zytan said:
Now. What's a better place other than using NUnit? Like for a really
small project? (no project is too small for unit testing.)

Even for a really small project, I'd use NUnit. Others recommend
MbUnit, but I don't know that that's any more suitable for small
projects than NUnit is.

Once you've used NUnit a few times, you'll think nothing of using it,
however small the project. Although I tend to put the tests into a
different project, you don't *have* to, if that's more overhead than
you want.
 
Even for a really small project, I'd use NUnit. Others recommend
MbUnit, but I don't know that that's any more suitable for small
projects than NUnit is.

Once you've used NUnit a few times, you'll think nothing of using it,
however small the project. Although I tend to put the tests into a
different project, you don't *have* to, if that's more overhead than
you want.

Ok, NUnit it is.

But wait. I consider TWO types of unit testing, something I've
conceived myself:

1. run-time unit testing that test a short sample, quickly, that does
as much as it can without getting in the way, which is removed for
final production. This shows incorrect code immediately on the next
run. It's the fastest unit testing feedback possible.

2. indepth testing, overnight testing, that runs for hours, testing
everything. This has everything that #1 can't have since it takes too
long.

Does NUnit do #1 as well? If not, it's not good enough. I thought I
should ask, since you said you put your unit testing in another
project, implying no run-time unit testing. (by 'run time', I just
mean it is run on every execute, preferably at the START, which is why
I want to run all my static c'tor on load.)

Zytan
 
Does NUnit do #1 as well? If not, it's not good enough. I thought I
should ask, since you said you put your unit testing in another
project, implying no run-time unit testing. (by 'run time', I just
mean it is run on every execute, preferably at the START, which is why
I want to run all my static c'tor on load.)

NUnit is specifically for frequent unit testing. It doesn't happen when
you run your application - it happens when you run your tests. That
should happen (IMO) much more often than you start your application.
Running tests should be pretty much as frequent as building - and you
need to write your unit tests appropriately so they run quickly.

Of course, you may decide to have different categories of unit tests,
some of which will take longer to run - but in general, tests which are
run most often are the most useful ones.
 
NUnit is specifically for frequent unit testing.

Ok great!
It doesn't happen when
you run your application - it happens when you run your tests. That
should happen (IMO) much more often than you start your application.

Ah, I see. Yes, unless you're like me and your application is the
unit tests. But, if my app wasn't, and the unit tests were in another
project, I can totally see why this test project would be run much
more often. It's the *reason* my app is run so often - for testing.
Running tests should be pretty much as frequent as building - and you
need to write your unit tests appropriately so they run quickly.

As i write code, I test it inside of my app by running it. So, if the
unit test project does the testing, then *that's* the code i'll be
running all the time.
Of course, you may decide to have different categories of unit tests,
some of which will take longer to run - but in general, tests which are
run most often are the most useful ones.

I agree. But, the longer tests have value in specific applications.
Such as stress testing multithreading apps. I've done that to confirm
bugs that should exist during mid-implementation, and confirm (within
reason) that they no longer exist once I've solve the problem.

I suppose this change of pace is what 'test driven development' is all
about? It means I've been doing it for a long time, just not quite on
track.

Zytan
 
Zytan said:
Ok great!


Ah, I see. Yes, unless you're like me and your application is the
unit tests. But, if my app wasn't, and the unit tests were in another
project, I can totally see why this test project would be run much
more often. It's the *reason* my app is run so often - for testing.

Right. Whereas I only run my application when I want to see "the big
picture" rather than to make sure the tests run correctly.
As i write code, I test it inside of my app by running it. So, if the
unit test project does the testing, then *that's* the code i'll be
running all the time.

I don't like the confusion between test code and real code - and in
particular, the fact that you'll have to get rid of the test code to
build the "release" version means that your tests won't be running
against the real code.

For instance, having a static constructor in a class subtly changes the
semantics of the class - see
http://pobox.com/~skeet/csharp/beforefieldinit.html
So if you only have a static constructor in a class for test purposes,
you'll be changing the semantics of that class when you remove that
static constructor.
I agree. But, the longer tests have value in specific applications.
Such as stress testing multithreading apps. I've done that to confirm
bugs that should exist during mid-implementation, and confirm (within
reason) that they no longer exist once I've solve the problem.

Yes, that's fine - but they're not unit tests. It's often useful to use
a unit test framework to build/run such tests, but they're not unit
tests.
I suppose this change of pace is what 'test driven development' is all
about? It means I've been doing it for a long time, just not quite on
track.

Test driven development means more than just writing unit tests for
code. It means writing the tests before the code exists in the first
place. The effect of that is that you write code which is always
testable, and your interfaces tend to be usable, because they're driven
by what the caller wants to do, rather than what the class wants to
expose.
 
As i write code, I test it inside of my app by running it. So, if the
I don't like the confusion between test code and real code - and in
particular, the fact that you'll have to get rid of the test code to
build the "release" version means that your tests won't be running
against the real code.

I don't follow what you mean here.

I run my unit test in debug and release, but in the final-release,
those calls become blank functions (only for speed purposes, if I
could run them, and report errors back home, I'd be happy to do this,
if it didn't have any side effects of slowing the app).
For instance, having a static constructor in a class subtly changes the
semantics of the class - seehttp://pobox.com/~skeet/csharp/beforefieldinit.html
So if you only have a static constructor in a class for test purposes,
you'll be changing the semantics of that class when you remove that
static constructor.

I would just leave the static c'tor, and make the unit test function
call a blank function (or remove the call). The static c'tor has no
unit test code in it, other than the call to the unit test function.
Yes, that's fine - but they're not unit tests. It's often useful to use
a unit test framework to build/run such tests, but they're not unit
tests.

Hmm? But, they have pretty much the same code. Only the quick unit
test differs in cases where I cannot make a quick version of the
longer unit test. The longer unit test has everything the quick one
has, and more. It has the same function calls, but it calls them
more. I fail to see how they aren't exactly the same thing -- unit
tests. They test my units. One does a more thorough job. I wish it
could do it every compile, but my computer is just not fast enough.
So, the quick test is more unlike a unit test than the long test, if
either, since it doesn't do the full job.

Are you saying there's a strict definition of what 'unit test' means?
Test driven development means more than just writing unit tests for
code. It means writing the tests before the code exists in the first
place. The effect of that is that you write code which is always
testable, and your interfaces tend to be usable, because they're driven
by what the caller wants to do, rather than what the class wants to
expose.

Yes, actually, I knew that. I had read up on it a bit. It's like
coding backwards, a bit. And I haven't been doing that at all.

Zytan
 
Zytan said:
I don't follow what you mean here.

I run my unit test in debug and release, but in the final-release,
those calls become blank functions (only for speed purposes, if I
could run them, and report errors back home, I'd be happy to do this,
if it didn't have any side effects of slowing the app).

It still means that the code is different at test time to normal
release.
I would just leave the static c'tor, and make the unit test function
call a blank function (or remove the call). The static c'tor has no
unit test code in it, other than the call to the unit test function.

Then you're getting a (slight) performance penalty for having a static
constructor in every class. It means the JIT can't perform some
optimisations when accessing static members of the class.
Hmm? But, they have pretty much the same code. Only the quick unit
test differs in cases where I cannot make a quick version of the
longer unit test. The longer unit test has everything the quick one
has, and more. It has the same function calls, but it calls them
more. I fail to see how they aren't exactly the same thing -- unit
tests. They test my units. One does a more thorough job. I wish it
could do it every compile, but my computer is just not fast enough.
So, the quick test is more unlike a unit test than the long test, if
either, since it doesn't do the full job.

Are you saying there's a strict definition of what 'unit test' means?

If it's just testing a single unit, that's fine - sorry, your previous
description of "stress testing multithreading apps" suggested that it
was testing the whole application, rather than a single class.
Yes, actually, I knew that. I had read up on it a bit. It's like
coding backwards, a bit. And I haven't been doing that at all.

It takes a while to get used to, and it's not *always* suitable, but it
can produce fabulous results.
 
I run my unit test in debug and release, but in the final-release,
It still means that the code is different at test time to normal
release.

Very true. While it shouldn't matter, I have seen bugs where
independent pieces of code have dependencies, and it could just be
where the first static c'tor is run. But, hopefully, the unit testing
should solve those exact problems before they could become a problem.

I thought maybe the unit test could be left in, as an even faster
version of the normal one that is run on every execute. Something
that takes 1/100th of a second, or 1/10th of a second maximum. And it
could report to home base if there's an error, and continue on. I've
never liked that debug code disappears at release time, and there's
release specific code that will handle as many errors as it can, since
it's too late to call Debug.Assert when it's on the customer's
machine. It'd be nice if something, anything, could be done, at least
during the first 0.1 seconds of launch to test a few things, and
report home about possible issues. This is something I highly doubt
anyone does.
Then you're getting a (slight) performance penalty for having a static
constructor in every class. It means the JIT can't perform some
optimisations when accessing static members of the class.

Oh, ok.

Zytan
 
Zytan said:
Very true. While it shouldn't matter, I have seen bugs where
independent pieces of code have dependencies, and it could just be
where the first static c'tor is run.

C# should not have much of the classic C/C++ unpredictable
behavior for various memory related bugs.

But there are a fundamental problem proving that the
the unit test code itself is the only difference between
what you tested and what you put in production.

Arne
 
Back
Top