all groups > c# > february 2007 >
You're in the

c#

group:

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


TypeInitializationException / forcing all static c'tors to run on startup Zytan
2/28/2007 6:22:38 PM
c#:
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
Re: TypeInitializationException / forcing all static c'tors to run on startup Marc Gravell
2/28/2007 9:28:30 PM
[quoted text, click to view]

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
Re: TypeInitializationException / forcing all static c'tors to run on startup Jon Skeet [C# MVP]
3/1/2007 12:00:00 AM
[quoted text, click to view]

I'd have a look at the stack traces carefully - they should show which
class is involved.

[quoted text, click to view]

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...

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Re: TypeInitializationException / forcing all static c'tors to run on startup Zytan
3/1/2007 12:50:09 PM
[quoted text, click to view]

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
Re: TypeInitializationException / forcing all static c'tors to run on startup Zytan
3/1/2007 12:51:53 PM
[quoted text, click to view]

Ok, thanks Marc. Your suggestions aren't much different from what I'm
doing now.

Zytan


Re: TypeInitializationException / forcing all static c'tors to run on startup Zytan
3/1/2007 12:56:18 PM
[quoted text, click to view]

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
Re: TypeInitializationException / forcing all static c'tors to run on startup Zytan
3/1/2007 1:09:57 PM
[quoted text, click to view]

Yes, that's true. So I need to catch this. Duh.

[quoted text, click to view]

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
Re: TypeInitializationException / forcing all static c'tors to run on startup Zytan
3/1/2007 6:19:53 PM
[quoted text, click to view]

This only works if I F9 on the static c'tor itself. It won't step
into it when it is invoked automatically.

[quoted text, click to view]

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
Re: TypeInitializationException / forcing all static c'tors to run on startup Jon Skeet [C# MVP]
3/1/2007 8:58:03 PM
[quoted text, click to view]

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...

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Re: TypeInitializationException / forcing all static c'tors to run on startup Jon Skeet [C# MVP]
3/1/2007 9:06:55 PM
[quoted text, click to view]

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.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Re: TypeInitializationException / forcing all static c'tors to run on startup Jon Skeet [C# MVP]
3/2/2007 12:00:00 AM
[quoted text, click to view]

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.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Re: TypeInitializationException / forcing all static c'tors to run on startup Zytan
3/2/2007 8:38:36 AM
[quoted text, click to view]

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
Re: TypeInitializationException / forcing all static c'tors to run on startup Zytan
3/2/2007 11:20:18 AM
[quoted text, click to view]

Ok great!

[quoted text, click to view]

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.

[quoted text, click to view]

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.

[quoted text, click to view]

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
Re: TypeInitializationException / forcing all static c'tors to run on startup Zytan
3/2/2007 1:29:24 PM
[quoted text, click to view]

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).

[quoted text, click to view]

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.

[quoted text, click to view]

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?

[quoted text, click to view]

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
Re: TypeInitializationException / forcing all static c'tors to run on startup Jon Skeet [C# MVP]
3/2/2007 5:59:28 PM
[quoted text, click to view]

<snip>

[quoted text, click to view]

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.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Re: TypeInitializationException / forcing all static c'tors to run on startup Jon Skeet [C# MVP]
3/2/2007 7:37:35 PM
[quoted text, click to view]

Right. Whereas I only run my application when I want to see "the big
picture" rather than to make sure the tests run correctly.

[quoted text, click to view]

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.

[quoted text, click to view]

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.

[quoted text, click to view]

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.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Re: TypeInitializationException / forcing all static c'tors to run on startup Jon Skeet [C# MVP]
3/3/2007 12:00:00 AM
[quoted text, click to view]

It still means that the code is different at test time to normal
release.

[quoted text, click to view]

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.

[quoted text, click to view]

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.

[quoted text, click to view]

It takes a while to get used to, and it's not *always* suitable, but it
can produce fabulous results.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Re: TypeInitializationException / forcing all static c'tors to run on startup Zytan
3/4/2007 4:45:06 PM
[quoted text, click to view]

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.

[quoted text, click to view]

Oh, ok.

Zytan
Re: TypeInitializationException / forcing all static c'tors to run on startup Arne_Vajhøj
3/5/2007 8:12:57 PM
[quoted text, click to view]

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.

AddThis Social Bookmark Button