tag:blogger.com,1999:blog-85148333154792187362024-02-20T20:54:18.313+03:00Fresh.ThoughtsRandom revelations on .Net programming and other earthly stuffuluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comBlogger64125tag:blogger.com,1999:blog-8514833315479218736.post-61238244436653233642011-06-02T16:18:00.000+04:002011-06-02T16:18:37.673+04:00Look who's got a new home!Finally I have built a new Web site for Ivonna, a <a href="http://ivonna.biz/">tool for testing Asp.Net sites</a>. So, I decided to move all my blogging efforts to the new site, and give it all my love (not really). I do have a couple of great posts there already, on <a href="http://ivonna.biz/blog.aspx?filterby=TDD">Test Driven Development</a> and other stuff. Expect more to come in the nearest future.<br />
<br />
Enjoy!uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-14369508628018363732011-01-11T22:43:00.001+03:002011-01-15T14:52:13.895+03:00A Flush In The NightOften you want to do some "fix" on your data before pushing it to the database. Typically it's some auditty thingie -- CreatedBy and UpdatedOn kind of stuff. After spreading it all around your application, you finally decide you should keep these things in one place.<br />
<a href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=646967" rel="tag" style="display:none;"> codeproject </a><br />
If you, like me, is an NHibernate user, most likely you find advice to use a <a href="http://www.nhforge.org/doc/nh/en/index.html#manipulatingdata-interceptors">custom IInterceptor</a> or <a href="http://ayende.com/Blog/archive/2009/04/29/nhibernate-ipreupdateeventlistener-amp-ipreinserteventlistener.aspx">IPreUpdateEventListener</a>. Both are quite ugly solutions, since you have to manipulate the raw state values that are already read from the entity and are ready to be saved to the database. What's even worse, in the latter case you should sync it manually with the entity properties as well. One may think that the original code had been ported from Hibernate before IDictionary was invented (I do understand that there might be some excuses, like performance considerations for example). Find the index of the required field in one array, then fix the value at the corresponding index in another one. Oh joy!<br />
<br />
So, it's quite understandable that I wanted a more elegant solution. Just "fix" the entity before being saved, and also do it in a more, well, object oriented fashion. Naturally this should happen just before the property values are read.<br />
<br />
So, I put a breakpoint on a property getter and started the debugger. Turned out the property was read by an instance of NHibernate.Event.Default.DefaultFlushEntityEventListener, which leads me to believe that its OnFlushEntity method is what actually turns my properties into arrays of raw values. Further investigation showed that this listener is an element of an array of IFlushEntityEventListener-s. So, my plan (which, unsurprisingly, succeeded), was to put my custom implementation in this array <i>before</i> the default one.<br />
<br />
Just show us the code! I hear you say. Ok, ok, I'm coming to that. Suppose you have a base entity class (but you're not quite sure, 'cause there might be some 3rd party entities floating around). You just add a template method to it called EnsureConsistency, or PerformAudit, whatever. Here is my custom listener:<br />
<br />
<pre style="font-family: consolas"><span
style="font-weight: 700;color: #eaeaac">public</span> <span
style="font-weight: 700;color: #eaeaac">class</span> <span
style="color: #f0dfaf">CustomFlushEntityEventListener :</span>
<span
style="color: #2b91af">IFlushEntityEventListener</span> {
<span style="font-weight: 700;color: #eaeaac">public</span> <span
style="font-weight: 700;color: #eaeaac">void</span> <span
style="color: #dfdfbf">OnFlushEntity</span>(<span style="color: #f0dfaf">FlushEntityEvent</span> <span
style="color: #dfdfbf">@event</span>) {
<span style="font-weight: 700;color: #eaeaac">var</span> <span
style="color: #dfdfbf">entity</span> = <span style="color: #dfdfbf">@event</span>.<span
style="color: #dfdfbf">Entity</span> <span
style="font-weight: 700;color: #eaeaac">as</span> <span
style="color: #f0dfaf">EntityBase</span>;
<span style="font-weight: 700;color: #eaeaac">if</span> (<span
style="color: #dfdfbf">entity</span> != <span
style="font-weight: 700;color: #eaeaac">null</span>)
<span style="color: #dfdfbf">entity</span>.<span
style="color: #dfdfbf">EnsureConsistency</span>();
}
}</pre>Now you have your class, here is how to tell NHibernate it should use it (during application startup):<br />
<pre style="font-family: consolas"><span style="color: #dfdfbf">configuration</span>.<span
style="color: #dfdfbf">SetListeners</span>(<span style="color: #2b91af">ListenerType</span>.<span
style="color: #dfdfbf">FlushEntity</span>,
<span style="font-weight: 700;color: #eaeaac">new</span> <span
style="color: #2b91af">IFlushEntityEventListener</span>[]
{
<span style="font-weight: 700;color: #eaeaac">new</span> <span
style="color: #f0dfaf">CustomFlushEntityEventListener</span>(),
<span style="font-weight: 700;color: #eaeaac">new</span> <span
style="color: #f0dfaf">DefaultFlushEntityEventListener</span>()
});</pre><br />
Here "configuration" is an instance of NHibernate.Cfg.Configuration, and the code should be run before you build you SessionFactory. The result is, for each entity being flushed, its EnsureConsistency method is being called. The entity itself knows what to do (if anything) in this case. Audit, denormalization, whatever.<br />
<br />
Now I do feel like a real Pro. Please tell me I am.<br />
<br />
<b>Update.</b> <a href="http://jfromaniello.blogspot.com">José F. Romaniello</a> published a response on the <a href="http://groups.google.com/group/nhusers">nhusers</a> Google group, in which he notes that the aforementioned method is being executed for every damn entity, not just for the changed ones. I need to rewrite the code. It seems like I have to inherit from DefaultFlushEntityEventListener and use its IsUpdateNecessary method in order to update just the changed entities. Thanks José!uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.com0tag:blogger.com,1999:blog-8514833315479218736.post-86553061929888211192010-07-12T23:01:00.004+04:002010-08-21T23:00:39.272+04:00Just can't plug this in, baby!I've just lost about half a day fighting with a stupid StructureMap exception:<br />
<blockquote><span class="logStreamMarker-Exception"><span class="logStreamMarker-ExceptionType">StructureMap<wbr></wbr>.Exceptions<wbr></wbr>.StructureMapConfigu<wbr></wbr>rationException</span><wbr></wbr>: <wbr></wbr><span class="logStreamMarker-ExceptionMessage">StructureMap <wbr></wbr>configuration <wbr></wbr>failures<wbr></wbr>:<br />
Error<wbr></wbr>: <wbr></wbr> <wbr></wbr>104<br />
Source<wbr></wbr>: <wbr></wbr> <wbr></wbr>Registry<wbr></wbr>: <wbr></wbr> <wbr></wbr>StructureMap<wbr></wbr>.ConfigurationExpres<wbr></wbr>sion,StructureMap<br />
Type <wbr></wbr>Instance <wbr></wbr>'bf0f9bf6-304d-4d7b-<wbr></wbr>9cd4-59437e94eb10' <wbr></wbr><wbr></wbr>(Smart <wbr></wbr>Instance <wbr></wbr>for <wbr></wbr>System<wbr></wbr>.Data<wbr></wbr>.SqlClient<wbr></wbr>.SqlClientFactory)<wbr></wbr> <wbr></wbr>cannot <wbr></wbr>be <wbr></wbr>plugged <wbr></wbr>into <wbr></wbr>type <wbr></wbr>System<wbr></wbr>.Data<wbr></wbr>.Common<wbr></wbr>.DbProviderFactory, <wbr></wbr>System<wbr></wbr>.Data, <wbr></wbr>Version=2<wbr></wbr>.0<wbr></wbr>.0<wbr></wbr>.0, <wbr></wbr>Culture=neutral, <wbr></wbr>PublicKeyToken=b77a5<wbr></wbr>c561934e089<br />
--------------------<wbr></wbr>--------------------<wbr></wbr>--------------------<wbr></wbr>--------------------<wbr></wbr>--------------------<wbr></wbr>-<br />
<br />
</span><span class="logStreamMarker-StackTrace"> <wbr></wbr> <wbr></wbr> <wbr></wbr>at <wbr></wbr>StructureMap<wbr></wbr>.Diagnostics<wbr></wbr>.GraphLog<wbr></wbr>.AssertFailures<wbr></wbr>()<wbr></wbr><br />
<wbr></wbr> <wbr></wbr> <wbr></wbr>at <wbr></wbr>StructureMap<wbr></wbr>.Container<wbr></wbr>.Configure<wbr></wbr>(Action`1 <wbr></wbr>configure)<wbr></wbr><br />
<wbr></wbr> <wbr></wbr> <wbr></wbr>at <wbr></wbr>StructureMap<wbr></wbr>.ObjectFactory<wbr></wbr>.Configure<wbr></wbr>(Action`1 <wbr></wbr>configure)<wbr></wbr><br />
</span></span></blockquote>My actual code was this:<br />
<blockquote>ObjectFactory.Configure(expr =><br />
{ <br />
<span class="blsp-spelling-error" id="SPELLING_ERROR_0">expr</span>.<span class="blsp-spelling-error" id="SPELLING_ERROR_1">For</span><DbProviderFactory>().<span class="blsp-spelling-error" id="SPELLING_ERROR_2">Use</span><SqlClientFactory>();<br />
});<br />
<br />
</blockquote><br />
<span class="blsp-spelling-error" id="SPELLING_ERROR_3">What</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_4">do</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_5">you</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_6">mean</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_7">by</span> "<span class="blsp-spelling-error" id="SPELLING_ERROR_8">cannot</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_9">be</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_10">plugged</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_11">in</span>", <span class="blsp-spelling-error" id="SPELLING_ERROR_12">and</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_13">why</span> Google <span class="blsp-spelling-error" id="SPELLING_ERROR_14">can</span>'t <span class="blsp-spelling-error" id="SPELLING_ERROR_15">help</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_16">me</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_17">here</span>???<br />
<br />
<span class="blsp-spelling-error" id="SPELLING_ERROR_18">So</span>, a <span class="blsp-spelling-error" id="SPELLING_ERROR_19">couple</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_20">of</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_21">hours</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_22">later</span> (<span class="blsp-spelling-error" id="SPELLING_ERROR_23">and</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_24">with</span> a <span class="blsp-spelling-error" id="SPELLING_ERROR_25">big</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_26">help</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_27">from</span> <a href="http://cthru.codeplex.com/"><span class="blsp-spelling-error" id="SPELLING_ERROR_28">CThru</span> </a><span class="blsp-spelling-error" id="SPELLING_ERROR_29">and</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_30">Reflector</span>), <span class="blsp-spelling-error" id="SPELLING_ERROR_31">and</span> I <span class="blsp-spelling-error" id="SPELLING_ERROR_32">find</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_33">the</span> StructureMap.Graph.TypeRules.CanBeCast <span class="blsp-spelling-error" id="SPELLING_ERROR_34">method</span>, <span class="blsp-spelling-error" id="SPELLING_ERROR_35">which</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_36">is</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_37">not</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_38">just</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_39">about</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_40">casting</span>, <span class="blsp-spelling-error" id="SPELLING_ERROR_41">but</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_42">says</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_43">no</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_44">when</span>, <span class="blsp-spelling-error" id="SPELLING_ERROR_45">among</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_46">other</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_47">things</span>, <span class="blsp-spelling-error" id="SPELLING_ERROR_48">the</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_49">concrete</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_50">type</span> (<span class="blsp-spelling-error" id="SPELLING_ERROR_51">SqlClientFactory</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_52">in</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_53">our</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_54">case</span>) <span class="blsp-spelling-error" id="SPELLING_ERROR_55">has</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_56">no</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_57">default</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_58">constructor</span>.<br />
<br />
<span class="blsp-spelling-error" id="SPELLING_ERROR_59">Ok</span>, I <span class="blsp-spelling-error" id="SPELLING_ERROR_60">can</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_61">understand</span>. <span class="blsp-spelling-error" id="SPELLING_ERROR_62">StructureMap</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_63">doesn</span>'t <span class="blsp-spelling-error" id="SPELLING_ERROR_64">know</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_65">how</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_66">to</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_67">create</span> a <span class="blsp-spelling-error" id="SPELLING_ERROR_68">concrete</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_69">instance</span>. <span class="blsp-spelling-error" id="SPELLING_ERROR_70">How</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_71">about</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_72">this</span>:<br />
<blockquote>expr.ForRequestedType<DbProviderFactory>().Use(SqlClientFactory.Instance);</blockquote>Still no luck:<br />
<blockquote><span class="logStreamMarker-Exception"><span class="logStreamMarker-ExceptionType">StructureMap<wbr></wbr>.Exceptions<wbr></wbr>.StructureMapConfigu<wbr></wbr>rationException</span><wbr></wbr>: <wbr></wbr><span class="logStreamMarker-ExceptionMessage">StructureMap <wbr></wbr>configuration <wbr></wbr>failures<wbr></wbr>:<br />
Error<wbr></wbr>: <wbr></wbr> <wbr></wbr>104<br />
Source<wbr></wbr>: <wbr></wbr> <wbr></wbr>Registry<wbr></wbr>: <wbr></wbr> <wbr></wbr>StructureMap<wbr></wbr>.ConfigurationExpres<wbr></wbr>sion,StructureMap<br />
Type <wbr></wbr>Instance <wbr></wbr>'42b890e6-54dc-457e-<wbr></wbr>897a-3e8becc7d0fb' <wbr></wbr><wbr></wbr>(Object<wbr></wbr>: <wbr></wbr> <wbr></wbr>System<wbr></wbr>.Data<wbr></wbr>.SqlClient<wbr></wbr>.SqlClientFactory)<wbr></wbr> <wbr></wbr>cannot <wbr></wbr>be <wbr></wbr>plugged <wbr></wbr>into <wbr></wbr>type <wbr></wbr>System<wbr></wbr>.Data<wbr></wbr>.Common<wbr></wbr>.DbProviderFactory, <wbr></wbr>System<wbr></wbr>.Data, <wbr></wbr>Version=2<wbr></wbr>.0<wbr></wbr>.0<wbr></wbr>.0, <wbr></wbr>Culture=neutral, <wbr></wbr>PublicKeyToken=b77a5<wbr></wbr>c561934e089<br />
</span></span></blockquote>This is more weird, but a look into the code tells me that we still require the target type to have a default constructor (cause we call the same method). Must be a bug in StructureMap. Too bad, since that would be the most clear and logical solution.<br />
<br />
Finally this one worked for me:<br />
<blockquote>expr.ForRequestedType<DbProviderFactory>() .AsSingletons(). TheDefault.Is.ConstructedBy (ctx => SqlClientFactory.Instance);</blockquote><br />
Have fun!uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-33223704334321482182010-07-05T20:54:00.000+04:002010-07-05T20:54:39.363+04:00Testing Asp.Net pages with Telerik's JustMockIt is always nice when a competitor publishes a piece of their code. You can always sneak into the comments and, like, look, I'm better! and put a link to your blog where you show your version proudly, and get a massive following.<br />
<br />
Guess what, this is what I'm doing right now commenting on the <a href="http://weblogs.asp.net/mehfuzh/archive/2010/04/29/playing-with-aspx-page-cycle-using-justmock.aspx">Mehfuz's post.</a> But the main thing I realized reading his post is that this is the perfect example of how using mocks in certain situations can turn testing into a nightmare. The following is not a problem with JustMock, it's a problem with trying to write a unit test involving a complex framework, and isolating parts of it not meant to be isolated.<br />
<br />
<span style="font-size: x-small;">(Disclaimer: I do understand that the purpose of the original post is not to teach us how to test Asp.Net pages, but to demonstrate the capabilities of JustMock. So, my intent is not to prove that the author is wrong, but rather to take his example as a perfect situation where mock should absolutely <i>not</i> be used.)</span><br />
<br />
So, in order to write the test, we have to<br />
<ol><li>Mock the <span style="color: #2b91af;">HttpBrowserCapabilities </span> class and stub a couple of its properties so that it returns <span style="font-style: italic;">something</span> when needed.</li>
<li>Mock the <span style="color: #2b91af;">HttpRequest</span> class (of <span style="font-style: italic;">course</span>) and make the mock return our mocked Browser.</li>
<li>Mock the <span style="color: #2b91af;">HttpResponse</span> class as well.</li>
<li>Mock the <span style="color: #2b91af;">HttpContext</span> class and stub its Request and Response properties (make the getters return our mock instances).</li>
<li>Finally, we are stubbing the <span style="color: #2b91af;">Page.</span>RenderControl method, and it's unclear whether we do it to avoid exceptions, or just for fun.</li>
</ol>The main purpose is to test whether the Page instance fires all (well, just some) its lifecycle events, and it's done not using mocks but rather adding event handlers (since we already have our Page instance).<br />
<br />
Why do we have to mock all these classes? Why do we have to fire up Reflector and dig into the Framework source in order to make our test pass? Because we have this idea that unit testing means testing a particular class in isolation. Somehow all calculator examples left us with an idea that "unit" == "class".<br />
<br />
Now, let's back off a bit and consider this: we are testing a high-level ProcessRequest method, which does a lot of lower-level calls to various classes, which are tightly coupled with each other. So, I think it's logical to say that our "unit" is a good part of the System.Web assembly. With that assumption, everything becomes simple: we don't test just our Page instance, we test the whole unit. Assuming we are the developers of the framework, we can also test the lower level methods which have less dependencies, so that we can mock them more easily.<br />
<br />
Back to our integration test, here's what it looks like when we use <a href="http://sm-art.biz/Ivonna.aspx">Ivonna</a>. I have omitted all asserts for clarity; instead, we just write messages to the console, as we would in an exploratory test:<br />
<blockquote><pre style="font-family: consolas;">[Test]
public void TestingPageEvents()
{
var session = new TestSession();
var request = new WebRequest("Default.aspx");
request.EventHandlers.Page_Init =
(sender, e) => Console.WriteLine("Init fired");
request.EventHandlers.Page_Load =
(sender, e) => Console.WriteLine("Load fired");
session.ProcessRequest(request);
}
</pre></blockquote>This code executes a test against a "real" Web page, with a "real" HttpContext and other necessary objects, so it gives us much more valuable information about the behavior of our system in "real world" situations.<br />
<br />
Check out a fresh version of Ivonna <a href="http://sm-art.biz/Ivonna.aspx">here</a>.uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-90848409420694425132010-06-18T11:38:00.003+04:002010-06-18T15:17:50.041+04:00C-eeing Thru Your Code<a href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=646967" rel="tag" style="display: none;"> codeproject </a><br />Ladies and gentlemen, let me introduce you to this exciting library, <a href="http://cthru.codeplex.com/">CThru</a>. (I planned to add several jokes here, but changed my mind). This is an open source AOP framework built on top of <a href="http://typemock.com/">Typemock Isolator</a>. Recently I added several improvements to the built-in aspects, and thought I might write a blog post about it.<br /><br />CThru requires Typemock Isolator to be installed on the target box, so you probably want to use it in your test projects. CThru does not require you to modify the original code, nor the compiled binaries, so you're free to use it on, say, BCL libraries (except for mscorlib). It works by intercepting method calls and add or change their behavior. Each aspect is responsible for deciding which calls to intercept by implementing the ShouldIntercept method. You can make a decision based on the target instance, class name, or method name. For example, you could apply it to all implementors of a particular interface, or for all types in a particular namespace.<br /><br />In order to make it work, you add all necessary aspects by calling CThruEngine.AddAspect(), then call CThruEngine.StartListening(). The cleanup is done by calling CThruEngine.StopListeningAndReset().<br /><br />So, how do you write your own aspect? First, you inherit from the abstract Aspect class, and implement the ShouldIntercept method. As I said before, it determines the condition for which the aspect is applied. To add specific behavior, you should override the MethodBehavior or ConstructorBehavior methods. By default, your code is run before the actual method is invoked. You can also skip the original method, return custom value, or throw an exception by manipulating the properties of the DuringCallbackEventArgs valued argument. If you want to add some behavior <span style="font-style: italic;">after</span> the original method is invoked, you can execute the Aspect.CallOriginalMethod method (don't forget to set e.MethodBehavior = MethodBehaviors.SkipActualMethod so that it isn't called twice).<br /><br />There are aspects that are generic in nature: the behavior is the same, but they are applied in different situation, so it doesn't make sense to hardcode the ShouldIntercept method. For example, the Stub aspect just ignores the method call, but which call it ignores should be determined by the code that uses the aspect. So, there's a convenient base class called "CommonAspect". It makes it possible to pass the intercepting decision in the constructor argument. For example, if you want to ignore all methods with names starting with "My", you write:<br /><blockquote>CThruEngine.AddAspect(new Stub(info => info.MethodName.StartsWith("My")));<br /></blockquote>That said, let's review some of the built-in aspects:<br /><ul><li>SkipAllByTypeName -- very simple aspect, designed to illustrate how aspects should be written. Skips all method calls of classes that contain the specified string in their names.<br /></li><li>MissingMethodAspect -- implements Ruby-like behavior in VB.Net (when you try and execute a non-existent method, it invokes the method called "method-missing" instead).</li><li>TraceAspect -- traces all intercepted calls to the console (or the supplied TextWriter instance), optionally with the stack trace.</li><li>TraceResultAspect -- same but traces the results as well. Due to the CThru limitation, all calls invoked by the traced call are not traced (unlike with TraceAspect).</li><li>DebugAspect -- if you have attached the debugger, it pauses the execution before calling the intercepted method. Very useful for investigating the state of the system at a particular point, when you don't have access to the code at that point.</li><li>Stub -- just ignore the call and return null. ToDo: implement returning a custom value.</li></ul>Several projects that are built on top of, or developed using, CThru:<br /><ul><li>SilverUnit, a framework for testing Silverlight applications. <a href="http://cthru.codeplex.com/">Bundled with CThru</a>.</li><li><a href="http://Balder.codeplex.com">Balder</a>. Managed 2D and 3D graphics engine, targetting Silverlight, Xna and OpenGL.</li><li><a href="http://sm-art.biz/Ivonna.aspx">Ivonna</a>, an Asp.Net unit and integration testing tool.<br /></li></ul><br />So, whether you just need some exploratory testing, or building a domain-specific test framework, CThru can save you a lot of effort.uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-13921960942341651202010-06-14T22:11:00.020+04:002010-06-17T17:40:38.521+04:00On structuring your tests<a href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=646967" rel="tag" style="display: none;"> codeproject </a><br />The ideas presented here are nothing new; however, a <a href="http://blogs.microsoft.co.il/blogs/dhelper/archive/2010/06/06/when-to-use-the-setup-attribute.aspx">recent discussion</a> with Dror Helper made me want to state my views on this subject (and make the whole world agree with me, whatever it takes), because to be honest, despite my best efforts in meditation, when I see a class called "MyClassTester" it makes me.. <strike>wanna start a holy war</strike> nervous.<br /><br />The idea is, if you do TDD, you don't start with a class, because if you do, you already have some design before you have written any tests. So, you start with a user story. Ant let it be a Web app, to be more concrete. Here it goes:<blockquote><span style="font-style: italic;">When a user fills the registration form correctly and hits the "Register" button, several things happen:<br /></span><ul><li style="font-style: italic;">she becomes, in some sense, "registered" in the system;</li><li style="font-style: italic;">an email is sent, containing the confirmation link;</li><li><span style="font-style: italic;">she's redirected to a particular screen.</span></li></ul><span style="font-style: italic;"><blockquote></blockquote></span></blockquote>Now, if I were to start writing unit tests for a particular class, which class would it be? The specs say nothing about classes or such. So, first, I decide that it's going to be an MVC app, like all the cool guys doing these days. And I'm going to start with the most exciting thing: my controller. So, I'm creating a class called AccountControllerTester or something. Next, I have to write a test, so I meditate over the requirements, and here's what I think:<br /><ul><li>"Registered" is kinda vague, but let's do it with the built-in Membership system. I'll inject this service into my controller, mock the service in my test and verify the call to it.<br /></li><li>Email is easy. A service again, I'll write it later (after the lunch), let's use an interface for the moment.<br /></li><li>Redirection is just return View(".."). Easy to test.<br /></li></ul>So you end up with either one test with three asserts (which is a bad practice), or three test methods related to one particular feature. What makes it a mess is that you're going to add more tests: related to input validation, and to the other features that are handled by this controller: password change and retrieval, email confirmation etc. For every action method, you can have 5-10 tests. On the other hand, the actual confirmation email sending belongs to a different class, so you probably put the test there, together with other email-related tests.<br /><br />You see, one big problem is that each test class becomes huge. But what's more important, it is hard to tell what your system does. One purpose of tests is documentation, and it should be readable for outsiders. If I am to figure out the behavior of the system in the registration process, where should I look? How do I know that part of it is in the AccountControllerTests, and another part is in the EmailServiceTests?<br /><br />And still another problem is that you just wrote a lot of code, but made <span style="font-weight: bold;">zero</span> business value with it. I mean, I can't register at your site yet! And won't be able until you write all the pieces and connect them together (for which you probably should write an integration test).<br /><br />To summarize, what you get with this approach is:<br /><ul><li>premature, rather than test-driven, design;</li><li>potentially brittle tests (since they are coupled to your classes, you can't refactor easily);</li><li>huge test classes;</li><li>documenting your classes rather than your system;</li><li>no clear relationship between the specs and your tests;</li><li>no business value until you have all the pieces.</li></ul><h2>There's a better way</h2>Now, let's do it another way. Let's create a folder called Membership, and inside it a folder called "Registration". We're testing the case when we submit valid registration data, so let's make a test class called "IfSubmittedValidRegistrationData". The test methods will be called "ShouldSendConfirmationEmail" etc, so the test output will show something like,<br /><blockquote>WhenSubmittedValidRegistrationData.ShouldSendConfirmationEmail -- <span style="font-style: italic;">passed</span>.</blockquote>This is quite close to documenting your system!<br /><br />Now, you can still write it as a unit test for your controller, if you prefer, but I suggest you start with integration tests. I use <a href="http://sm-art.biz/Ivonna.aspx">Ivonna</a> for testing, and it makes it a lot easier: my "integration" is only server-side. In addition, I can use several built-in CThru aspects, like EmailSpy, and I can use a lightweight in-memory database. I initialize the posted values (Arrange) and execute the request (Act) in the FixtureSetup method, and all my test methods are one or two lines of code where I verify the results.<br /><ul><li>UserShouldBeRegistered -- I just check it via the MembershipAPI.</li><li>ShouldSendConfirmationEmail-- I use EmailSpy that prevents the message from being sent, and saves it for further investigation, so that I can verify that it contains the confirmation link, is being sent to the correct address etc.</li><li>ShouldRedirectToTheWelcomeScreen -- check the Ivonna.Framework.WebResponse.RedirectLocation property.<br /></li></ul>Now I can go the full Red-Green-Refactor way. I stuff all the code into my action method until all my tests pass. At this moment <span style="font-style: italic;">my system actually works</span>: I can register a user! But my code is ugly: it is a quick-and-dirty solution written just in order to make my tests pass. I want to make it better. So I refactor it.<br /><br />It's at the refactoring phase that unit tests can provide a big value. Yes we all know that unit testing can lead us to a much better design. But sometimes it is enough to do it mentally. For example, "how would I unit test my controller"? Oh yes, I should refactor the email-related code into a separate class, and do dependency injection. Probably extract an interface like IMessagingService and implement it as EmailService. Whatever. But I actually write a unit test only if I can think of a good name for it. EmailServiceTester totally won't do. TheConfirmationMessageShouldBeActuallySentByEmail is more like it (and the corresponding unit test for the controller is ShouldSendTheConfirmationMessage -- note that it doesn't mention "email"). But in this particular case, it's probably not worth it.<br /><br />There is another situation when we have a particular feature that produces some output depending on various inputs, and it's not a yes/no situation, like in the previous case. Take searching, for example. You start with an integration test, like before. And make it work. For one of several search form parameters, you know that the search produces the correct results that appear in a grid on the search results page. It would be wasteful to write integration test for every search parameter. So, assume we already have it refactored into several units (note that I don't say "classes"): SearchParamsReader (this is actually the MVC Binder), TheThingThatGivesUsSearchResultsDependingOnTheSearchParams, and SearchResultsWriter (the one responsible for displaying the results). You make three subfolders in your Searching folder (which already contains the integration test), each responsible for the corresponding piece of functionality. Actually, it's probably worth it to make just one subfolder and test TheThingThat.. Again, you don't put everything for testing TheThing.. into one huge class, but you create several classes: SearchByKeyword, SearchByMinMaxPrice etc. This is unit, not integration, testing, and yet it corresponds to user requirements and documents the system behavior. I could refactor TheThing.. into several classes, I could rename it, and the tests won't break.<br /><h2>Here's the recipe for happiness</h2><ol><li>Make a folder corresponding to a feature, then a subfolder for a sub-feature etc, until you have a concrete action, like registration or search, or maybe a concrete context.</li><li>Inside, create a fixture for each combination of context + action (like "submitting a duplicate username") and name it accordingly (WhenSubmittedExistingUsername).</li><li>Put all preparation into the FixtureSetup method. You want it to be readable, so refactor all the nasty details into private methods and move them to the end.</li><li>Each check should go to a separate Test method. Name them so that they match the requirements.</li><li>More granular tests, if you need them, should go to subfolders.</li><li>If you can't think of a decent test name (something that doesn't use the class/method names), it's probably not worth writing (but might be useful for driving your design).<br /></li></ol>uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-32779866214462640802010-05-04T14:10:00.003+04:002010-05-04T14:49:47.196+04:00Fixing the namespace problem in VB.Net XML literalsRecently I tried to parse a Web page output using the shiny VB.Net syntax. I had an XElement representing a dropdown, and tried to count the options using something like<br /><blockquote>purposeChooser.<option>.Count</blockquote>Although I could clearly see that there is one child "option" element, it kept returning a zero. Then I realized that there might be some namespace trouble. Indeed, the top html tag had some namespace attached, and, naturally, it was inherited by the select (and the option) element. However, it didn't include a prefix, so how do I tell what to look for? The answer is, you can import an XML namespace just like you can a "regular" one, putting this at the top of your code:<br /><blockquote>Imports <xmlns:ns="http://www.w3.org/1999/xhtml"></blockquote>And now this expression<br /><blockquote>purposeChooser.<ns:option>.Count</blockquote>returns 1, as expected.uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-18446363615774527342010-04-17T13:18:00.003+04:002010-04-17T13:53:56.221+04:00Using the EditorFor method in MVC2 to display child collectionsI was very excited when I discovered the new DisplayFor and EditorFor extensions in the new MVC release. In fact, they look even better than the similar MVCContrib features.<br /><br />The only problem is that when I tried to render a child collection, it displayed nothing. This is kinda weird, because when your model <span style="font-style: italic;">is</span> a collection, it shows just fine. However, as <a href="http://blogs.msdn.com/stuartleeks/archive/2010/03/30/collections-and-asp-net-mvc-templated-helpers-displayfor-editorfor.aspx">this post</a> explains, anything complex enough (that is, not convertible to a string) is just filtered out.<br /><br />It turned out that it could be fixed relatively easily. You have to override the default Object template and fix the logic. Just create a view called Object.ascx in your Views/Shared/EditorTemplates folder, copy the default template from <a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html">here</a>, and modify the filtering logic. Took me a while, since I had to convert it to VB.Net. Here's the result:<br /><br /><%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl" %><br /><%@ Import Namespace="System.Globalization"%><br /><%@ Import Namespace="System.Linq" %><br /><br /><% If (ViewData.ModelMetadata.Model Is Nothing) Then%><br /> <%=ViewData.ModelMetadata.NullDisplayText%><br /><% Else%> <br /> <% If (ViewData.TemplateInfo.TemplateDepth > 3) Then%><br /> <%=Me.ViewData.ModelMetadata.SimpleDisplayText%><br /> <% Else%><br /> <% Dim props = From pm In Me.ViewData.ModelMetadata.Properties Where pm.ShowForEdit AndAlso Not ViewData.TemplateInfo.Visited(pm) For Each prop In props If prop.HideSurroundingHtml Then%><br /> <%= Html.Editor(prop.PropertyName) %><br /> <% Else Dim str As String = Html.Label(prop.PropertyName).ToHtmlString If Not String.IsNullOrEmpty(str) Then%><br /> <div class="editor-label"><%= Html.Label(prop.PropertyName) %></div><br /> <% End If%><br /> <div class="editor-field"><br /> <%= Html.Editor(prop.PropertyName) %><br /> <%= Html.ValidationMessage(prop.PropertyName, "*") %><br /> </div><br /> <% End If%><br /><br /><br /> <%Next%><br /> <% End If%><br /><% End If%><br /><br />Don't forget to check the line related to TemplateDepth. Originally, it makes a shallow copy: everything with the depth>1 is just displayed as a simple string. You might want to make this number greater, or remove the check entirely.uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-20475467058218921792010-04-09T23:30:00.003+04:002010-04-09T23:47:25.952+04:00Using the latest NHibernate features in your VB.Net code.No doubt you have tried the newest LINQ-to-NHibernate bits in your VB.Net application already. If you have gotten past retrieving all records from a specific table, you might been getting an exception similar to this one:<br /><br />System.Exception: Unrecognised method call in epression CompareString(aUser.Name, value(Web.Controllers.Membership.AccountMembershipService+_Closure$__1).$VB$Local_userName, False)<br /> at NHibernate.Impl.ExpressionProcessor.FindMemberExpression(Expression expression) in f:\Разные штуки\Visual Studio 2008\Projects\OpenSource\NHibernate\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line 170<br /> at NHibernate.Impl.ExpressionProcessor.ProcessSimpleExpression(BinaryExpression be) in f:\Разные штуки\Visual Studio 2008\Projects\OpenSource\NHibernate\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line 295<br /> at NHibernate.Impl.ExpressionProcessor.ProcessBinaryExpression(BinaryExpression expression) in f:\Разные штуки\Visual Studio 2008\Projects\OpenSource\NHibernate\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line 358<br /> at NHibernate.Impl.ExpressionProcessor.ProcessExpression(Expression expression) in f:\Разные штуки\Visual Studio 2008\Projects\OpenSource\NHibernate\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line 388<br /> at NHibernate.Impl.ExpressionProcessor.ProcessLambdaExpression(LambdaExpression expression) in f:\Разные штуки\Visual Studio 2008\Projects\OpenSource\NHibernate\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line 395<br /> at NHibernate.Impl.ExpressionProcessor.ProcessExpression[T](Expression`1 expression) in f:\Разные штуки\Visual Studio 2008\Projects\OpenSource\NHibernate\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line 406<br /> at NHibernate.Criterion.QueryOver`2.Add(Expression`1 expression) in f:\Разные штуки\Visual Studio 2008\Projects\OpenSource\NHibernate\nhibernate\src\NHibernate\Criterion\QueryOver.cs:line 568<br /> at NHibernate.Criterion.QueryOver`2.Where(Expression`1 expression) in f:\Разные штуки\Visual Studio 2008\Projects\OpenSource\NHibernate\nhibernate\src\NHibernate\Criterion\QueryOver.cs:line 248<br /> at NHibernate.Criterion.QueryOver`2.NHibernate.IQueryOver<troot,tsubtype>.Where(Expression`1 expression) in f:\Разные штуки\Visual Studio 2008\Projects\OpenSource\NHibernate\nhibernate\src\NHibernate\Criterion\QueryOver.cs:line 619<br /><br />The code I have is quite innocent:<br />Return _session.QueryOver(Of User).Where(_<br /> Function(aUser) aUser.Name = userName).List().First<br /><br />It returns the first instance of the User class that matches the Name property. The problem is that the VB compiler transforms the lambda into something like<br />(CompareString(aUser.Name, value(Web.Controllers.Membership.AccountMembershipService+_Closure$__1).$VB$Local_userName, False) = 0)<br /><br />Now, CompareString is a shared method of the Microsoft.VisualBasic.CompilerServices.Operators class, which is probably not something the NHibernate developers expected to appear in a lambda. Time for a patch. A quick fix is to add the following piece of code in the beginning of the NHibernate.Impl.ExpressionProcessor.ProcessSimpleExpression method:<br /><br />if (be.Left.NodeType == ExpressionType.Call) {<br /> var left = (MethodCallExpression) be.Left;<br /> if (left.Method.Name == "CompareString") {<br /> return ProcessSimpleExpression(Expression.Equal(left.Arguments[0], left.Arguments[1]));<br /> }<br />}<br /><br />Actually, the CompareString method has 3 arguments. The third one, when set to false, signifies the literal comparison, while being set to true means textual (case insensitive) comparison. So, if you use the LIKE operator, you might want to check for left.Arguments[2].uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-17593236950666631422010-02-21T20:03:00.002+03:002010-02-21T20:07:04.932+03:00Ivonna 2.1 is outFinally, the next release of Ivonna is out! You can read more about this release <a href="http://sm-art.biz/ivonna-21-is-out.aspx">here</a>. For those of you unfamiliar with Ivonna, it is server-side <a href="http://sm-art.biz/Ivonna.aspx">Asp.Net unit and integration testing tool</a> I develop in partnership with TypeMock.uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-24419202299446411912010-01-28T18:41:00.002+03:002010-01-28T18:55:24.428+03:00Fixing the " 'Telerik.Web.UI.GridInsertionObject' does not contain a property with the name" problemTelerik's RadGrid has a handy possibility to insert a new object. Works fine with DataTables, but since I sure prefer using ObjectDataSources, sometimes I get the abovementioned exception when clicking the Insert button whenever the grid is empty.<br /><br />The problem is, the grid can't figure out the type of the new record when it doesn't have any records yet. This is sorta silly, since it is bound to an ObjectDataSource object and (theoretically) could get the class name from it. Anyway, it just creates an instance of Telerik.Web.UI.GridInsertionObject and then complains that it can't do the databinding.<br /><br />There are tons of solutions out there, even provided by the Telerik team, and they typically involve a lot of manual labour. Typically you would create an object yourself or provide some Dictionary with all properties initialized etc. Not exactly a DRY style of work.<br /><br />My solution is.. just return a generic List rather than an Enumerable for the Select method of your ObjectDataSource. For example, this<br /><blockquote style="color: rgb(51, 51, 51);">Return From product In Me.FetchAll Where product.CategoryId = categoryId</blockquote>will give an exception when trying to add a record. Change it to<br /><blockquote style="color: rgb(51, 51, 51);">Return (From product In Me.FetchAll Where product.CategoryId = categoryId).ToList()</blockquote>and you'll be fine.<br /><blockquote></blockquote>uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-16293016956309350312009-12-31T01:54:00.003+03:002009-12-31T02:41:37.161+03:00ExecutionEngineException in Silverlight 3I just started playing with Silverlight (you know, waiting for the patform to mature and stuff), plus I've got WCF on the other end, which I'm learning from scratch as well. So, I managed to make a working but messy project, and after that (ok, actually after it stopped compiling) I decided to start from scratch (ok, just copypaste the relevant bits of the working code).<br /><br />This is when my FireFox started to quietly die instead of showing me the results of the WCF query.<br /><br />Debugging gave me the exception, and it better didn't. It was the ill-famous ExecutionEngineException, something that, as MSDN itself admits, Should Never Happen. What's worse, the exception was somehow related to a MessageBox. I forgot to mention that I used an evaluation version of some control, and it was displaying a message box spontaneously inviting me to buy the full version. Googling told me that message boxes do cause such issues.<br /><br />Anyway, the actual problem was that I forgot to configure my service in web.config, so the actual exception was quite different. I was calling the service asynchronously, so the exception happened on a non-UI thread, and it could somehow interfere with the abovementioned message box.<br /><br />So, my guess is that the exception has been caused by these ingredients, in order of appearance:<br /><ol><li>a message box;</li><li>unhandled exception</li><li>on a non-UI thread</li><li>possibly, some code in the Application_UnhandledException handler.<br /></li></ol>uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-6949920468565179302009-12-21T18:36:00.002+03:002009-12-21T20:10:37.066+03:00Experiment in persistence ignoranceHaving read a lot about how cool NHibernate is in helping with persistence ignorance, I decided to check if I can go far enough with it. More precisely, I decided to check if I can live without the Id property on my entities.<br /><br />Now, you might ask, how do I show say products of a particular category. I mean, if I have a Web site, there should be some Url for it, and this Url should look like Products.aspx?CategoryId=1 or Products/List/CategoryId/1, whatever, but you should include the Id somehow. The answer is, you can always use session.Get() or session.Load() to get the entity by its Id, and the reverse is also true: you can use session.GetIdentifier() to retrieve the entity's Id.<br /><br />At the same time, I switched from entities to models in my pages (WebForms or MVC). Doing this was a big relief because I felt myself dirty when adding a lot of properties to my entities just for the purpose of viewing (like, CategoryName, ItemCount etc). On the other hand, it means a lot of additional boring work: creating model classes and adding the mapping code. Fortunately, the first task is easy with the help of T4 templates, while the second is what AutoMapper (and other mappers) is created for.<br /><br />Long story short, even though I managed to automate a lot, including the custom mapping code, I still got a lot of places where I had to repetively write session.GetIdentifier() in order to retrieve the Id. So, I'd recommend leaving it in place, although it doesn't seem to make much sense in terms of my domain.<br /><br />Disclaimer: by entities, models and stuff I don't want to say that I'm doing DDD or any other cool stuff. The system is too simple for that. Nevertheless, separating models from entities, provided it doesn't require much effort, pays off in my case.uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-49978617674102856052009-07-13T01:09:00.002+04:002009-07-13T01:37:38.136+04:00Interacting with embedded Flash content in FlexI've been doing some Flex development lately (sorry Microsoft), so I though I might share a little discovery of mine in return to numerous advices from the community.<br /><br />While creating a complex Flash application, it is a common situation that the graphical content and animations created by designers in Flash, while developers load them into a Flex application. While loading is pretty straightforward, often you need to manipulate them, i.e., play a different clip, detect then a clip reaches a certain label, etc. What you usually do is have your flash content have a certain base class (called Document class) which is known to your flex app, and cast loader.content to this class once it's loaded.<br /><br />The problem is, the above solution doesn't work with embedded content. Don't know whether it is a bug or a feature, but the content cannot be cast to the document class. The docs say, use embedded content for static stuff like images or static swfs. Well, my content was an intro to a module, and I had to detect it's finished playing in order to hide it and show the actual content. On the other hand, I wanted it embedded so that my preloader would work correctly. In addition, the module had a base class, and I wanted to have the intro-related code in the base class, while embedding the intro into the actual module.<br /><br />So, utilizing some hints from the community plus a little debugging session, and here's my solution (I still don't see any reason why it works this particular way).<br /><br /><ol><li>Embed the flash content via the metadata tag: <br />[Embed(source="../../flex_bin/someflash.swf", mimeType="application/x-shockwave-flash")]<br /> private var SWFBytes:Class;</li><li>Use it in your SWFLoader (note the source):<br /><mx:swfloader id="introLoader" source="{new SWFBytes()}" scalecontent="false" creationcomplete="intro_complete(event)"></li><li>Handle the CreationComplete event like this:<br />var content:MovieClip= this["introLoader"].content as MovieClip;<br />var loader:Loader = content.getChildAt(0) as Loader;<br />var intro:RoomIntro = RoomIntro(loader.content);</li></ol>Here's the "intro" variable we're interested it, RoomIntro is the document class of the flash movie. Note that the content of our loader is a movie clip, but it's not what we need: it has a child, which is another loader, and the content of *this* loader is what we actually need. In short, we need the content of the first child of the content of our loader.<br /><br />Tricky, eh?uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-63161712028715980172009-05-19T18:59:00.001+04:002009-05-19T19:30:22.277+04:00Get a free TypeMock Isolator + Ivonna<a href="http://www.typemock.com/">Unit Testing</a> ASP.NET? <a href="http://www.typemock.com/ASP.NET_unit_testing_page.php">ASP.NET unit testing</a> has never been this easy.<br /><br />Typemock is launching a new product for ASP.NET developers – the <strong>ASP.NET Bundle</strong> - and for the launch will be giving out <span style="color: rgb(0, 102, 0);"><strong>FREE licenses</strong></span> to bloggers and their readers.<br /><br />The ASP.NET Bundle is the ultimate ASP.NET unit testing solution, and offers both <a href="http://www.typemock.com/">Typemock Isolator</a>, a <a href="http://www.typemock.com/">unit test</a> tool and <a href="http://sm-art.biz/Ivonna.aspx">Ivonna</a>, the Isolator add-on for <a href="http://sm-art.biz/Ivonna.aspx">ASP.NET unit testing</a>, for a bargain price.<br /><br />Typemock Isolator is a leading <a href="http://www.typemock.com/">.NET unit testing</a> tool (C# and VB.NET) for many ‘hard to test’ technologies such as <a href="http://typemock.com/sharepointpage.php">SharePoint</a>, <a href="http://www.typemock.com/ASP.NET_unit_testing_page.php">ASP.NET</a>, <a href="http://www.typemock.com/ASP.NET_unit_testing_page.php">MVC</a>, <a href="http://www.typemock.com/wcfpage.php">WCF</a>, WPF, <a href="http://www.typemock.com/Silverlight_unit_testing_page.php">Silverlight</a> and more. Note that for <a href="http://www.typemock.com/Silverlight_unit_testing_page.php">unit testing Silverlight</a> there is an open source Isolator add-on called <a href="http://www.typemock.com/Silverlight_unit_testing_page.php">SilverUnit</a>.<br /><br />The first 60 bloggers who will blog this text in their blog and <a href="http://blog.typemock.com/2009/05/get-free-typemock-licenses-aspnet.html">tell us about it</a>, will get a Free Isolator ASP.NET Bundle license (Typemock Isolator + Ivonna). If you post this in an ASP.NET <strong>dedicated</strong> blog, you'll get a license automatically (even if more than 60 submit) during the first week of this announcement.<br /><br />Also 8 bloggers will get an <strong>additional 2 licenses</strong> (each) to give away to their readers / friends.<br /><br />Go ahead, click the following link for <a href="http://blog.typemock.com/2009/05/get-free-typemock-licenses-aspnet.html">more information </a>on how to get your free license.<script src="http://shots.snap.com//client/inject.js?site_name=0" type="text/javascript"></script>uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-80121294345303101762008-11-24T00:19:00.004+03:002009-04-17T15:10:51.853+04:00Unit testing private methods.. not again!This is a question often raised on TDD forums. How do I test a private (protected, internal, Friend) method. Those not so bold ask, should I? A typical answer is, if you want to test a private method, extract it into another class and make it public, and make the first class hold a private instance of this new class.<br /><br />I think that this answer is too general. While newbies generally want a universal recipe (and this one is good enough), I'd start gathering more info. Like a Zen master wannabe, I'd ask a question which should be an answer to the original one. Oh, and then I'd ask some more.<br /><br />So, <span style="font-weight: bold;">why</span> do you want to test it?<br /><br />Is it just the idea that every method in a class should be tested? Then resist this temptation.<br /><br />Another option is that your public method that calls your private method just started acting weird. Well, the next question, what portion of the code just changed that caused this behavior? Still another option, that you <span style="font-weight: bold;">dared to write some code without writing the test first</span>, and now you're trying to cover your ass. My humble advice would be to delete the bastard and start all over.<br /><br />But there are several other important questions to ask. Does the private method have a well defined semantic meaning? If yes, why do you resist making it public? Are you afraid that someone will call it? Why? Are you lazy to document it?<br /><br />The only reason I can accept here is that your private method puts a system into an inconsistent state. For example, you can have a public Transfer method, which takes money from one account and moves it to another. The two private methods would be manipulation the two respective accounts. If you call one of them, some money would be, say, taken from one account but not moved to the other. In this case, it is unacceptable to move the method to another class and make it public: calling it from outside would be a disaster. In this case, I would simply refactor the system so that no such method exists.<br /><br />As this begins to sound <span style="font-style: italic;">very</span> confusing, I'd give some reasons for choosing what to test.<br /><ul><li>A test is a usage example, a documentation in an executable form. A <span style="font-style: italic;">unit test</span> is, more or less, a feature: you provide a code example on how to use your product. This might be wrong for desktop or Web applications, but the essence remains the same. It would be weird to provide a usage example for a private method.</li><li>One of the main reasons for hiding a method is "encapsulation", as the proponents put it. In other words, you want to hide the implementation details. This is usually a good idea, given that you have a solid reason to do so. Typically, the reason is that you might change it in the future. So, the simple logic conclusion is that you shouldn't test it, since it makes your tests brittle. On the other hand, if you make it public, nothing prevents you from making a changed version later, and keeping this one unchanged (or maybe enhanced, but keeping the same functionality).</li><li>Still another reason: if I make all these methods public, my API will be bloated, and my customers confused. This is a valid reason only for those who are lazy enough to write a good doc. Other possible solutions are: use the EditorBrowsableAttribute; move this method to another class (here we go again!), and place this class in the Internals namespace (or invent some ever more scary name).<br /></li></ul><script src="http://shots.snap.com//client/inject.js?site_name=0" type="text/javascript"></script><script src="http://shots.snap.com//client/inject.js?site_name=0" type="text/javascript"></script><script src="http://shots.snap.com//client/inject.js?site_name=0" type="text/javascript"></script>uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-5732466774680427472008-11-10T16:29:00.002+03:002008-11-10T17:08:31.466+03:00Localizing the GridView date valuesThis is weird. I should have bumped into this problem ages ago. The problem is, whenever I'm trying to enter a localized date into a datagrid, it is saved as if it were an American date. I.e., 1.02.2008, which is the 1st of February, is saved as 01/02/08 (January 2nd).<br /><br />Setting the page's Culture to Russian didn't work. A quick Reflectoring showed that ObjectDataSource uses InvariantCulture for parsing the supplied values.<br /><br />The solution is sort of ugly: use the grid's Updating event and swap the string with the corresponding date:<br /><div style="background: rgb(63, 63, 63) none repeat scroll 0% 0%; font-family: Consolas; font-size: 8pt; color: rgb(220, 220, 204); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"> <pre style="margin: 0px;"> <span style="color: rgb(234, 234, 172); font-weight: bold;">Protected</span> <span style="color: rgb(234, 234, 172); font-weight: bold;">Sub</span> <span style="color: rgb(223, 223, 191);">gridDjSchedules_RowUpdating</span>(<span style="color: rgb(234, 234, 172); font-weight: bold;">ByVal</span> <span style="color: rgb(223, 223, 191);">sender</span> <span style="color: rgb(234, 234, 172); font-weight: bold;">As</span> <span style="color: rgb(234, 234, 172); font-weight: bold;">Object</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">ByVal</span> <span style="color: rgb(223, 223, 191);">e</span> <span style="color: rgb(234, 234, 172); font-weight: bold;">As</span> <span style="color: rgb(223, 223, 191);">System</span>.<span style="color: rgb(223, 223, 191);">Web</span>.<span style="color: rgb(223, 223, 191);">UI</span>.<span style="color: rgb(223, 223, 191);">WebControls</span>.<span style="color: rgb(223, 223, 191);">GridViewUpdateEventArgs</span>)</pre> <pre style="margin: 0px;"> <span style="color: rgb(223, 223, 191);">e</span>.<span style="color: rgb(223, 223, 191);">NewValues</span>(<span style="color: rgb(200, 145, 145);">"TheDate"</span>) = <span style="color: rgb(223, 223, 191);">Convert</span>.<span style="color: rgb(223, 223, 191);">ToDateTime</span>(<span style="color: rgb(223, 223, 191);">e</span>.<span style="color: rgb(223, 223, 191);">NewValues</span>(<span style="color: rgb(200, 145, 145);">"TheDate"</span>), <span style="color: rgb(223, 223, 191);">System</span>.<span style="color: rgb(223, 223, 191);">Globalization</span>.<span style="color: rgb(223, 223, 191);">CultureInfo</span>.<span style="color: rgb(223, 223, 191);">CurrentCulture</span>)</pre> <pre style="margin: 0px;"> <span style="color: rgb(234, 234, 172); font-weight: bold;">End</span> <span style="color: rgb(234, 234, 172); font-weight: bold;">Sub</span></pre> </div> <br />Looks like it's time to create a custom control..<br /><script src="http://shots.snap.com//client/inject.js?site_name=0" type="text/javascript"></script>uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-27721972883793702662008-10-14T13:13:00.002+04:002008-10-14T13:35:55.824+04:00In search of a developer-friendly CMSAfter a lot of frustration with DotNetNuke, which was quite a while ago, and some recent adventures with <a href="http://www.mojoportal.com/">mojoPortal </a>(by the way, Joe, the maintainer and almost a single contributor for this project, does excellent job fixing all the bugs in no time after they are reported), I decided that no way I'm gonna use a CMS again, ever. Yes, I used it on my own site, <a href="http://sm-art.biz">http://sm-art.biz</a>, but then, it required no custom modules.<br /><br />The problem is, all these frameworks focus on how simple it is to get your site up and running, provided that you don't need any additional functionality, other than included in one of the million modules. When you start to add something that is unique to this site, you quickly realize that it's much simpler to start from scratch than follow the module development guidelines. At the very least, they require that youк module inherits from a base class, and is initialized in such a way that it is totally impossible to test it outside of the framework.<br /><br />So, here are the qualities of a CMS I wish existed. Has anybody seen this puppy?<br /><br />1. Respect the composition-over-inheritance principle. Don't make me inherit, let me use a plain old ascx control.<br />2. Make it simle to plug this control into my site. Don't make me write these manifests and put sql scripts in a predefined place. However, I do want this possibility to exist, and also custom installer classes.<br />3. Use Convention over Configuration, it's the latest trend.<br />4. Make it decoupled. I don't want to see a column "totalforumposts" in the users table.<br />5. Use Ivonna for testing, I don't want a buggy product :)<br />6. I want to go from a regular site to a CMS and back in small steps. I want to be able to use various parts of it independently and switch off other parts if necessary. It should be more like a framework. There shouldn't be one "switch to a CMS" step, but rather start using various pieces one by one.<br /><br />Until I see something like this, I'll be trying to write my own.<br /><script src="http://shots.snap.com//client/inject.js?site_name=0" type="text/javascript"></script>uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-72890362888906042192008-07-29T15:07:00.002+04:002009-04-17T15:12:44.640+04:00A Dose Of Code<div id="ctl01_mainContent_ctl02_divSingleItem" class="modulecontent"><p>While developing Ivonna, I often have to figure out how various stuff in System.Web works. Sometimes Reflectoring it is enough; however, there are some particularly gigantic methods, full of loops and branches, that are hard to figure out. In any case, Reflector gives a static picture, while I need to see it live. Sure now you can download the source and debug through it (although I've never managed), but the real hackers don't use debuggers, preferring asserts and console output.<br /><br />Anyway, I needed to inject some code (or stop the debugger) at some particular method call in some assembly I don't have the code of. I've been using the TypeMock's MockMethodCalled event for it. After a while, it became tedious, so I decided to put some repetitive code into a class. Soon I found that it could have a couple of more useful features, but I wanted it to be really simple, and I didn't need much, so I'm keeping it to one class, three methods, three relaxed evenings of development.<br /><br /><b>How does it work.</b></p> <ol><li>Create an instance of Njector using the target type (this is something like creating a mocked instance).</li><li>Add one or more injected pieces of code (something similar to adding expectations).</li><li>Call the main code, in which an instance of the target type is created, and the target methods are called.</li><li>The injected pieces are invoked before, after, or instead of the target methods. You also gain access to the target instance, target method parameters, and return value (in case you use the After injection).</li></ol> <p><br /><b>Example</b><br />This is something that I actually used to figure out how the System.Web.HttpMultipartContentTemplateParser class parses the input using the ParseIntoElementList method. This method has several loops and branches, so it's not easy to find out what's happening given a particular piece of data. What you see here is just the preparation; after that I prepare the input data and call the framework code using Ivonna, but that's outside the scope of this post. GetPrivateField() is an utility extension method doing guess what.</p> <div style="background: rgb(63, 63, 63) none repeat scroll 0% 50%; color: rgb(220, 220, 204); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Consolas;font-size:8pt;"><div style="background: rgb(63, 63, 63) none repeat scroll 0% 50%; color: rgb(220, 220, 204); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Consolas;font-size:8pt;"> <p style="margin: 0px;"><span style="color: rgb(234, 234, 172); font-weight: bold;">var</span> <span style="color: rgb(223, 223, 191);">web</span> = <span style="color: rgb(240, 223, 175);">Assembly</span>.<span style="color: rgb(223, 223, 191);">GetAssembly</span>(<span style="color: rgb(234, 234, 172); font-weight: bold;">typeof</span>(<span style="color: rgb(223, 223, 191);">System</span>.<span style="color: rgb(223, 223, 191);">Web</span>.<span style="color: rgb(223, 223, 191);">HttpRequest</span>));</p> <p style="margin: 0px;"><span style="color: rgb(234, 234, 172); font-weight: bold;">var</span> <span style="color: rgb(223, 223, 191);">parserType</span> = <span style="color: rgb(223, 223, 191);">web</span>.<span style="color: rgb(223, 223, 191);">GetType</span>(<span style="color: rgb(200, 145, 145);">"System.Web.HttpMultipartContentTemplateParser"</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">true</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">true</span>);</p> <p style="margin: 0px;"><span style="color: rgb(234, 234, 172); font-weight: bold;">var</span> <span style="color: rgb(223, 223, 191);">inject</span> = <span style="color: rgb(234, 234, 172); font-weight: bold;">new</span> <span style="color: rgb(240, 223, 175);">Njector</span>(<span style="color: rgb(223, 223, 191);">parserType</span>);</p> <p style="margin: 0px;"><span style="color: rgb(223, 223, 191);">inject</span>.<span style="color: rgb(223, 223, 191);">After</span>(<span style="color: rgb(200, 145, 145);">"GetNextLine"</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">null</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">delegate</span>(<span style="color: rgb(234, 234, 172); font-weight: bold;">object</span> <span style="color: rgb(223, 223, 191);">target</span>, <span style="color: rgb(240, 223, 175);">MethodBase</span> <span style="color: rgb(223, 223, 191);">method</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">object</span>[] <span style="color: rgb(223, 223, 191);">parameters</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">object</span> <span style="color: rgb(223, 223, 191);">retValue</span>) {</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"GetNextLine: {0}"</span>, <span style="color: rgb(223, 223, 191);">retValue</span>);</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"Pos={0}"</span>, <span style="color: rgb(223, 223, 191);">target</span>.<span style="color: rgb(223, 223, 191);">GetPrivateField</span>(<span style="color: rgb(200, 145, 145);">"_pos"</span>));</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"line={0}"</span>, <span style="color: rgb(223, 223, 191);">target</span>.<span style="color: rgb(223, 223, 191);">GetPrivateField</span>(<span style="color: rgb(200, 145, 145);">"_lineStart"</span>));</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"partDataStart={0}"</span>, <span style="color: rgb(223, 223, 191);">target</span>.<span style="color: rgb(223, 223, 191);">GetPrivateField</span>(<span style="color: rgb(200, 145, 145);">"_partDataStart"</span>));</p> <p style="margin: 0px;">});</p> <p style="margin: 0px;"><span style="color: rgb(223, 223, 191);">inject</span>.<span style="color: rgb(223, 223, 191);">After</span>(<span style="color: rgb(200, 145, 145);">"AtBoundaryLine"</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">null</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">delegate</span>(<span style="color: rgb(234, 234, 172); font-weight: bold;">object</span> <span style="color: rgb(223, 223, 191);">target</span>, <span style="color: rgb(240, 223, 175);">MethodBase</span> <span style="color: rgb(223, 223, 191);">method</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">object</span>[] <span style="color: rgb(223, 223, 191);">parameters</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">object</span> <span style="color: rgb(223, 223, 191);">retValue</span>) {</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"AtBoundaryLine: {0}"</span>, <span style="color: rgb(223, 223, 191);">retValue</span>);</p> <p style="margin: 0px;">});</p> <p style="margin: 0px;"><span style="color: rgb(223, 223, 191);">inject</span>.<span style="color: rgb(223, 223, 191);">After</span>(<span style="color: rgb(200, 145, 145);">"AtEndOfData"</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">null</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">delegate</span>(<span style="color: rgb(234, 234, 172); font-weight: bold;">object</span> <span style="color: rgb(223, 223, 191);">target</span>, <span style="color: rgb(240, 223, 175);">MethodBase</span> <span style="color: rgb(223, 223, 191);">method</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">object</span>[] <span style="color: rgb(223, 223, 191);">parameters</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">object</span> <span style="color: rgb(223, 223, 191);">retValue</span>) {</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"AtEndOfData: {0}"</span>, <span style="color: rgb(223, 223, 191);">retValue</span>);</p> <p style="margin: 0px;">});</p> <p style="margin: 0px;"><span style="color: rgb(223, 223, 191);">inject</span>.<span style="color: rgb(223, 223, 191);">After</span>(<span style="color: rgb(200, 145, 145);">"ParsePartHeaders"</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">null</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">delegate</span>( <span style="color: rgb(234, 234, 172); font-weight: bold;">object</span> <span style="color: rgb(223, 223, 191);">target</span>, <span style="color: rgb(240, 223, 175);">MethodBase</span> <span style="color: rgb(223, 223, 191);">method</span>,<span style="color: rgb(234, 234, 172); font-weight: bold;">object</span>[] <span style="color: rgb(223, 223, 191);">parameters</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">object</span> <span style="color: rgb(223, 223, 191);">retValue</span>) {</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"ParsePartHeaders"</span>);</p> <p style="margin: 0px;">});</p> <p style="margin: 0px;"><span style="color: rgb(223, 223, 191);">inject</span>.<span style="color: rgb(223, 223, 191);">Before</span>(<span style="color: rgb(200, 145, 145);">"ParsePartData"</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">null</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">delegate</span>(<span style="color: rgb(234, 234, 172); font-weight: bold;">object</span> <span style="color: rgb(223, 223, 191);">target</span>, <span style="color: rgb(240, 223, 175);">MethodBase</span> <span style="color: rgb(223, 223, 191);">method</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">object</span>[] <span style="color: rgb(223, 223, 191);">parameters</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">object</span> <span style="color: rgb(223, 223, 191);">retValue</span>) {</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"ParsePartData Before"</span>);</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"Pos={0}"</span>, <span style="color: rgb(223, 223, 191);">target</span>.<span style="color: rgb(223, 223, 191);">GetPrivateField</span>(<span style="color: rgb(200, 145, 145);">"_pos"</span>));</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"line={0}"</span>, <span style="color: rgb(223, 223, 191);">target</span>.<span style="color: rgb(223, 223, 191);">GetPrivateField</span>(<span style="color: rgb(200, 145, 145);">"_lineStart"</span>));</p> <p style="margin: 0px;"> <span style="color: rgb(127, 159, 127);">//System.Diagnostics.Debugger.Break();</span></p> <p style="margin: 0px;">});</p> <p style="margin: 0px;"><span style="color: rgb(223, 223, 191);">inject</span>.<span style="color: rgb(223, 223, 191);">After</span>(<span style="color: rgb(200, 145, 145);">"ParsePartData"</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">null</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">delegate</span>(<span style="color: rgb(234, 234, 172); font-weight: bold;">object</span> <span style="color: rgb(223, 223, 191);">target</span>, <span style="color: rgb(240, 223, 175);">MethodBase</span> <span style="color: rgb(223, 223, 191);">method</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">object</span>[] <span style="color: rgb(223, 223, 191);">parameters</span>, <span style="color: rgb(234, 234, 172); font-weight: bold;">object</span> <span style="color: rgb(223, 223, 191);">retValue</span>) {</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"ParsePartData After"</span>);</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"Pos={0}"</span>, <span style="color: rgb(223, 223, 191);">target</span>.<span style="color: rgb(223, 223, 191);">GetPrivateField</span>(<span style="color: rgb(200, 145, 145);">"_pos"</span>));</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"line={0}"</span>, <span style="color: rgb(223, 223, 191);">target</span>.<span style="color: rgb(223, 223, 191);">GetPrivateField</span>(<span style="color: rgb(200, 145, 145);">"_lineStart"</span>));</p> <p style="margin: 0px;"> <span style="color: rgb(240, 223, 175);">Console</span>.<span style="color: rgb(223, 223, 191);">WriteLine</span>(<span style="color: rgb(200, 145, 145);">"partDataLength={0}"</span>, <span style="color: rgb(223, 223, 191);">target</span>.<span style="color: rgb(223, 223, 191);">GetPrivateField</span>(<span style="color: rgb(200, 145, 145);">"_partDataLength"</span>));</p> <p style="margin: 0px;">});</p> <p style="margin: 0px;"> </p> <p style="margin: 0px;"><span style="color: rgb(127, 159, 127);">//Prepare the data</span></p> <p style="margin: 0px;"><span style="color: rgb(127, 159, 127);">//Do the POST</span></p> <p style="margin: 0px;"><span style="color: rgb(127, 159, 127);">//The framework creates an instance of System.Web.HttpMultipartContentTemplateParser and calls its ParseIntoElementList method, </span></p> <p style="margin: 0px;"><span style="color: rgb(127, 159, 127);">//which in turn calls the methods like GetNextLine, AtBoundaryLine, etc.</span></p> <p style="margin: 0px;"><span style="color: rgb(127, 159, 127);">//After the GetNextLine method is called, our code is executed, and we're able to see the result. </span></p> </div></div></div><br />Download the source <a href="http://sm-art.biz/NJect.aspx">here</a>.<br /><br />Update: there's a much better project now, called <a href="http://www.codeplex.com/CThru">CThru</a>, developed by TypeMock.<br /><script src="http://shots.snap.com//client/inject.js?site_name=0" type="text/javascript"></script>uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.comtag:blogger.com,1999:blog-8514833315479218736.post-88919679713388177612008-05-29T23:47:00.003+04:002009-04-17T15:12:58.218+04:00Multiple AppDomains on a single WebI was getting some weird errors when using a <a href="http://neo.sourceforge.net/">Neo</a> ObjectContext on a Web as a global variable. This thing is supposed to be dependency-injected into factories and stuff, but I've set it to be a static property long time ago and saved me a lot of effort, since most stuff became possible with the Neo code generation tool.<br /><br />This was long before I learned that singletons are evil.<br /><br />Anyway, I've been getting very weird errors. Such as, I see a page with a record that should have been deleted, I refresh the page and it's not there, I refresh it again and it's there etc. It looked as if there were two contexts, and the record has been deleted from only one of them. However, since a Context was a static variable, there couldn't possibly be two contexts, right?<br /><br />Or so I thought. Recently, I've been investigating the whole remoting thing in connection with Ivonna, and I discovered the trivial fact that different static variables exist in different AppDomains. So, I thought that maybe there are two AppDomains for the same site? A quick experiment showed that this is true indeed, if there are two (almost) simultaneous requests.<br /><br />And the moral of the story is.. dunno, will figure out tomorrow.<script src="http://shots.snap.com//client/inject.js?site_name=0" type="text/javascript"></script>uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.com0tag:blogger.com,1999:blog-8514833315479218736.post-64018875362873594292008-05-14T12:22:00.003+04:002008-05-14T22:54:32.034+04:00LOLCode, DLR EditionThis is a code snippet that actually works.<br /><pre><span style="font-family: courier new;">HAI</span><br /><br /><span style="font-family: courier new;">CAN HAS STDIO?</span><br /><span style="font-family: courier new;">VISIBLE "HAI WORLD!"</span><br /><br /><span style="font-family: courier new;">I HAS A CODE ITZ "CRAZY"</span><br /><span style="font-family: courier new;">VISIBLE CODE</span><br /><br /><span style="font-family: courier new;">I HAS A NUMBR</span><br /><span style="font-family: courier new;">LOL NUMBR R 2</span><br /><span style="font-family: courier new;">VISIBLE NUMBR TIEMZ 2</span><br /><br /><span style="font-family: courier new;">I HAS A FIB</span><br /><span style="font-family: courier new;">I HAS A A ITZ 1</span><br />I HAS A B ITZ 0<br /><br />It's written in <a href="http://code.google.com/p/lolcode-dot-net/">LOLCode.NET</a>, a brand new .Net language that quickly gathers support among agile developers. <a href="http://www.hanselman.com/blog/TheWeeklySourceCode11LOLCodeDLREdition.aspx">Read the full story</a> on the Scott Hanselman's <a href="http://www.hanselman.com/blog/">blog</a>.</pre>uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.com0tag:blogger.com,1999:blog-8514833315479218736.post-6164470367518477822008-05-11T22:17:00.004+04:002009-04-17T15:13:37.259+04:00Activating the RecordLots of things happened since I last cared to blog. Here's the first one, chronologically. While I'm trying to not get too excited about Dependency Injection, I realized that it's about time to use some services in Inka, and I sort of needed an IoC container. My first idea was to use <a href="http://structuremap.sourceforge.net/">StructureMap</a> by <a href="http://codebetter.com/blogs/jeremy.miller/default.aspx">Jeremy Miller</a>, but I wanted an automocking container for my tests as well, and I was forced to choose <a href="http://www.castleproject.org/container/index.html">Castle Windsor</a>. Or so I thought at that time -- it turned out that, first, I didn't have time to implement these things, and second, StructureMap also has an automocking container. But that's not the point.<br /><br />The point is, I thought, hell, why not move to a decent ORM as well? Meaning Castle ActiveRecord.<br /><br />My first ORM was <a href="http://neo.sourceforge.net/">Neo</a> (Net Entity Objects, I think the name has been invented before The Matrix). Unlike Castle AR, which is really a nice interface for NHibernate, Neo is Active Record in a true sense. I'd even say, it's Typed DataSets Done Right. Each entity class is a wrapper over the DataRow class, so we can track the state (is it added, deleted, or modified) automatically. Each object is created via a factory, and added to the context automatically, so it can appear in your query results without being saved to a database. Cool. And also very convenient for testing.<br /><br />Speaking of testing, I still can't figure out how to test AR applications without a database connection.<br /><br />So, Neo is not for purists (nor is AR), they want POCOs. But I''m just a script kiddie, so it's OK for me. Neo's got a code generator, so I quickly enjoyed the idea and put all sorts of stuff into my templates, including some UI-related things. Don't blame me, I haven't heard about SoC in these days. In return, I managed to do some boilerplate stuff extra quickly.<br /><br />Unfortunately, there's a very small community around Neo, and the development seems to stop. I've fixed a few bugs, but never got to publishing the fixes (only recently I learned that I had violated the LPGL license). Also, it's pretty simple, and perhaps won't cover more complex situations, including fat query results.<br /><br />I'm only learning Active Record, and it has some very nice points (including a great graphic schema editor, Active Writer), but I've had some really weird moments with it. One, for example, is that I've been getting some weird exceptions that I wasn't able to reproduce in my tests. Almost intuitively, I invoked a Scope constructor at startup, and the problem was gone, although I never used the created scope variable anywhere! Turned out there's some dirty game with shared (static in C# :) variables here and there. I used to wonder why people hate these statics, now I know!<br /><br />I'd like to learn more about AR, but now I'm totally thrilled by <a href="http://sm-art.biz/Ivonna.aspx">Ivonna</a> being released soon, so I'm leaving the applied programming world for a while..<script src="http://shots.snap.com//client/inject.js?site_name=0" type="text/javascript"></script>uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.com0tag:blogger.com,1999:blog-8514833315479218736.post-67756188899497226752008-02-26T22:19:00.002+03:002008-02-26T22:24:20.986+03:00OopsHmm.. finally my layout engine for <a href="https://sourceforge.net/projects/inka">Inka</a> is ready. Or so I thought. All tests are green, well, some are yellow, but come on. I was sure that I over-tested it and began planning to dramatically reduce the number of tests -- I start a demo app and discover that everything looks wrong!uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.com0tag:blogger.com,1999:blog-8514833315479218736.post-67654597028688125232008-02-21T12:35:00.004+03:002009-04-17T15:16:57.153+04:00Just can't help it!Well, finally I'm at the point where I have to prepare an installer for Ivonna. Actually, I'm stuck at this point for about two weeks. Not because of installer itself, but because of the documentation. No, I diligently wrote all the xml comments, believe me. But these comments have to make way into a nice docs, preferably with some custom ("conceptual" in Sandcastle terms) content. And it has to be in Html Help 2.x format. This morning I finally discovered that my help can be viewed in the Document explorer. Was it because of the electricity been cut for a moment?<br /><br />Anyway, here's my recipe. I'll be using VS 2005 with the 2007 SDK, <a href="http://www.codeplex.com/Sandcastle/Release/ProjectReleases.aspx?ReleaseId=9921">Sandcastle January 2008 release</a>, and <a href="http://www.codeplex.com/DocProject/Release/ProjectReleases.aspx?ReleaseId=8252">DocProject 1.10.0 RC</a>.<br /><ol><li>Install the VS SDK.</li><li>Install Sandcastle. It is important to install it after the SDK, because the SDK contains its own version of Sandcastle, which is too old. Anyway, if you installed Sandcastle first accidentally, just edit your DXROOT environment variable so that it points to the Sandcastle's folder.<br /></li><li>Download and extract the <a href="http://www.codeplex.com/SHFB/Release/ProjectReleases.aspx?ReleaseId=9848">presentation file patches</a>. This fixes a bug in Sandcastle when you don't have a root topic.<br /></li><li>Install DocProject. A major annoyance is a bug in the 1.10 RC version: the Add-in looks for the Project toolbar that has more than 40 items. Mine had only 38. The suggested workaround is to download the code and patch it manually, but I couldn't afford that, so, instead I wrote a macro that added 3 ugly entries to my Project menu. Anybody interested? <span style="font-style: italic; font-weight: bold;">Update</span>: there's a 1.10.1 version that supposedly fixed this bug.<br /></li><li>Add a DocProject to your solution. You can add a DocSite project instead if you need online help (it will build the offline help as well).</li><li>You might want to modify some templates offered by the DocProject wizard. But don't remove the feedback section entirely -- you'll get a JavaScript error later.</li><li>Modify the AssemblyInfo.cs file to reflect your documentation title and organization.<br /></li><li>Don't ever rebuild the project -- it'll lose some essential files.</li><li>In the project wizard or later in the DocProject properties (available as an additional context menu item for your project), select "build html 2.0".</li><li>You might want to select the fastest build option -- choose "none" in the "build assembler options".</li><li>Now, after building the project, you have an HxS file in your output folder.</li><li>Unlike a chm file, you can't open it directly. Instead, you have to register it and navigate to it using the special ms-help protocol.</li><li>So, how do you register it?</li><li>The manual steps recommended copying a certain merge module from the sdk directory and manually editing it with Orca.</li><li>Like I was going to do that.</li><li>Actually I even did a first step.</li><li>But it turned out that there's a new kind of extensibility projects called "Help Integration Wizard". What you want is create a merge module that you'll add to your installation project. The wizard is pretty trivial, and it stores all its settings in the CollectionFiles folder, so you can edit them manually later.</li><li>At the first step, I chose the help file that I discovered in the Help/bin folder of my DocSite project.<br /></li><li>The wizard showed me the structure of my future help. It contained one topic, called "sample topic" or something. it was on the left pane, and on the right there were my topics, conveniently excluded from the future help. I renamed the sample topic to "Ivonna", and added my topics under that root topic.</li><li>I also chose the namespace for my help -- ivonna.docs.</li><li>However, building the project didn't work for me, the postbuild event (the one that actually edited the merge module) failed. Invoking it manually from the command line failed as well. So, I opened the executable in the Reflector, and it turned out that it has been designed specifically in order to hide the possible cause of an error. For example, the exception was coming from a logging statement that was inside a catch block, so it was cleverly hiding the real exception. Also, all exception messages came from some native calls, so, for example, "File not found" turned into "Invalid handle".<br /></li><li>So, I just wrote something that mimicked this app, and it somehow worked. Now I have a patched merge module that I can add to my installer. <span style="font-weight: bold; font-style: italic;">Update</span>: It turned out that the problem was with the path -- it contained cyrillic characters. Once I created another project in a different location, everything went smooth.</li><li>Now, you should add the merge module from this project to your setup. You should probably create a Help folder under your app folder, and choose it for the merge module files. Choose the merge module in your setup project, and choose the folder in the Properties, KeyOutput -> MergeModuleProperties -> Module Retargetable Folder.</li><li>By the way, you can see all installed help namespaces via a handy utility located here: \Program Files\Visual Studio 2005 SDK\2007.02\VisualStudioIntegration\Archive\HelpIntegration\Unsupported\Namespace.exe<br /></li><li>You probably want to include a shortcut to your documentation. It should be something like this: "%CommonProgramFiles%\Microsoft Shared\Help 8\dexplore.exe" /helpcol ms-help://ivonna.docs. Note that I put my namespace after the "ms-help://" stuff. Yes, you are even able to view it in IE.<br /></li><li>After you successfully made the installer, you discover that when the documentation opens it shows an empty page. If you want an introduction or something to appear, you should register it as "DefaultPage". Details can be found <a href="http://www.codeplex.com/DocProject/Thread/View.aspx?ThreadId=23252">here</a>.<br /></li><li>Modify your shortcut like this: "%CommonProgramFiles%\Microsoft Shared\Help 8\dexplore.exe" /helpcol ms-help://ivonna.docs /LaunchNamedUrlTopic DefaultPage.</li></ol>By the way, you can download Ivonna from my new site <a href="http://sm-art.biz/IvonnaDownload.aspx">here</a>, and view the online docs (produced with DocProject) <a href="http://ivonnadocs.sm-art.biz/">here</a>. I'll be blogging about Ivonna on my site's blog.<script src="http://shots.snap.com//client/inject.js?site_name=0" type="text/javascript"></script>uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.com0tag:blogger.com,1999:blog-8514833315479218736.post-3602075070358805832008-02-11T14:42:00.000+03:002008-02-11T14:45:44.304+03:00Inka movedInka has finally changed its Unix name at SourceForge. You can find it at https://sourceforge.net/projects/inka.<br /><br />Also, I'm finally building me a site, and there'll be a lot about Inka and how it should be used. Find it at <a href="http://sm-art.biz">http://sm-art.biz</a>.uluhttp://www.blogger.com/profile/09205790793910716812noreply@blogger.com0