Friday, October 24, 2008

Mock Example

Mocking is a great way to test a class in isolation. Not only can determinisitic results of the mocked class be forced, but parameters to the mocked object's methods can be tested.

Here is a unit test that uses mockito as its mocking framework. It is organized in the increasingly popular Arrange / Act / Assert format. This tests a yet to be written subclass of Spring's AbstractJDomPayloadEndpoint.

  1 @Test
2 public void validDepthOfField( ) throws Exception {
3 stub( _depthOfFieldCalculator.calculateDepthOfField( _expectedDofParams ) ).toReturn( _depthOfField );
5 final PhotoEndpoint photoEndpoint =
6 new PhotoEndpoint( _depthOfFieldCalculator );
7 final Element dofElem =
8 photoEndpoint.invokeInternal( _depthOfFieldRequest );
10 Assert.assertEquals( _depthOfField.getFarLimit(),
11 _parseDouble( dofElem, _farLimitExpression));
12 Assert.assertEquals( _depthOfField.getNearLimit(),
13 _parseDouble(dofElem, _nearLimitExpression));
14 Assert.assertEquals( _depthOfField.getHyperFocalDistance(),
15 _parseDouble(dofElem, _hyperFocusDistanceExpression));
16 }

  • Line 3: _depthOfFieldCalculator was mocked with mockito in JUnit's @Before. If calculateDepthOfField(...) is called with a object matching _expectedDofParams(equals overridden), _depthOfField will be returned. Important to note that if the calculateDepthOfField is called with the wrong parameter, the mock will return null.
  • Lines 5-6: Create a class that does not yet exist with our mock.
  • Lines 7-8: Call the endpoint's invoke method that is under test.
  • Lines 10-15: Assert that the returned Element is valid.

Labels: , ,

Friday, October 17, 2008

Passive View in Flex

Those interested in implementing the Model View Presenter design pattern with a Passive View should find the following (abbreviated) code of benefit.
  1 <?xml version="1.0"?> 
2 <mx:Application xmlns:mx=""
3 creationComplete="_onCreationComplete()"
4 implements="">
5 <mx:Script><![CDATA[
6 import;
7 import;
9 private var _photoPresenter:IPhotoPresenter;
11 private function _onCreationComplete():void {
12 _photoPresenter = new PhotoPresenter(this);
13 }
15 private function submitDofHandler(event:Event):void {
16 _photoPresenter.onSubmit();
17 }
19 public function get subjectDistance() : String {
20 return txt_subjectDistance.text;
21 }
22 public function set subjectDistance(subjectDistance:String) : void {
23 txt_subjectDistance.text = subjectDistance;
24 }
26 ]]></mx:Script>
27 <mx:Panel title="Depth of Field Calculator" height="75%" width="75%"
28 paddingTop="10" paddingLeft="10">
29 <mx:Grid id="grid_input" horizontalAlign="left" width="100%">
30 <mx:GridRow>
31 <mx:GridItem horizontalAlign="right">
32 <mx:Label text="Subject Distance"/>
33 </mx:GridItem>
34 <mx:GridItem>
35 <mx:TextInput id="txt_subjectDistance" text="10"/>
36 </mx:GridItem>
37 <mx:GridItem>
38 <mx:Label text="meters"/>
39 </mx:GridItem>
40 </mx:GridRow>
41 </mx:Grid>
42 </mx:Panel>
43 </mx:Application>

Line 4: this is how an ActionScript interface is implemented in a mxml file
Line 12: we construct the Presenter whose constructor takes a IPhotoView
Line 16: immediately hand off events to the Presenter

Labels: ,

Monday, October 13, 2008

NHibernate Optimization

I recently spent some time optimizing a highly concurrent web application's database access code. This particular application uses NHibernate for its ORM.

This post enumerates some of the "lessons-learned".
  • Set show_sql to true. Viewing the SQL that NHIbernate runs while in development will help developers catch redundant or unnecessary database calls.
  • Use HQL aggregation. HQL aggregate functions are much more performant than loading all of the objects and aggregating with code in memory.
  • By default, enable lazy initialization. 
  • Use batch-fetching where appropriate. In a one-to-many mapping, if most of the time more than one item needs to be accessed in the "many" collection enable batch-fetching by setting the batch-size. The first time one item in the "many" is asked for NHibernate will prefetch "batch-size" items.
  • Use the right fetch strategy.
  • Retrieve objects by ID if possible. NHibernate has a first-level cache, which is only utilized when an object's retrieval is by ID.
  • Use second-level cache for read-only associations.
  • Multi queries can reduce database round-trips.
  • Hand-code ADO.Net. Use a SQL profiler and a code profiler to find bottlenecks.If a bottleneck is found that can't be fixed by changing the fetch strategy, HQL, or caching, dropping down to ADO .Net is probably the best option. This doesn't mean swapping out NHIbernate completely, but just the slow query.

Labels: , ,

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]