StrataFrame Forum

Unit test BO without actually connect to DB

http://forum.strataframe.net/Topic12382.aspx

By Chan - 11/2/2007

Hi,

I would like to test my BO biz rule. However, I don't want to connect to actual database, so that the testing can completed faster. Additionally, I would like to have "dependecy injection" for data layer so that I could prepare my test data there.



What is the recommended approach to do this in SF environment?



Thank you
By Peter Jones - 11/3/2007

Hi Chan,

Not that I've ever used them but SF has methods for reading XML files and creating datasets. Perhaps you could put some code into ParentFormLoading to populate the BO's dataset from a local XML file.

Cheers, Peter

By Trent L. Taylor - 11/5/2007

Chan,

Just manually call the CheckRules method on the BO.  This does not make a trip and you can manually force the BO rules to be checked.

By Chan - 11/12/2007

Trent L. Taylor (11/05/2007)
Chan,



Just manually call the CheckRules method on the BO. This does not make a trip and you can manually force the BO rules to be checked.




Hi,

Some of my BzRules method required to retrieve info from other tables for checking. I am thinking possible to "hijack" my custom method that retrieve extra data or data access layer for it.
By Trent L. Taylor - 11/13/2007

I am sorry.  I do not understand your post.  Could you give me more details as to what you are trying to accomplish.  Thanks.
By Chan - 11/13/2007

Hi,

I have OrdersBO, OrderDetailsBO. I am writing unit test for both business rules. In OrdersBO CheckRules, it will retrieve customer's info to determine discount and taxes by calling this._Customers.GetCustomerType().



As you suggested in previous post, I can just call CheckRules method to check for BizRules. However, in my case it need to retrieve additional data (customer info in this case).



My question is, how could I "hijack" GetCustomerType() so that it will not need to connect to database?



Thank you
By Greg McGuffey - 11/13/2007

You might consider adding to the fill method that is used, then creating a custom property that accesses the field in the customers table:



-- SQL might be this

Select

OrderID

--... Other order fields here

,CustomerID -- FK in order table

, (Select CustomerType From Customers As c Where c.CustomerID = Orders.CustomerID) AS CustomerType

From Orders




In a custom property, access this field in the underlying datatable:



property int CustomerType () {

get { return Me.CurrentRow.Item("CustomerType") }

}




This allows the data from Customers to be accessed when the primary data is retrieved, so another trip to the db isn't necessary when checking rules. However, it also means your OrdersBO needs to know about the Customers table, so it isn't as encapsulated.



Another thought would be to cache a CustomersBO with the needed data when you load OrdersBO. By "needed data" I mean you could fill with just the data needed for checking rules, not all of the customers data (I.e. maybe just the customerid and the customer type). This might be the entire customer table.



Both of these have problems for new orders (hence the potential need to grab all customers in the second method), as the customer id won't be filled when the BO is filled. If you use the second method, you'll be able to get the info on any customer that existed when you cached the data...which means handling updating the cache if a customer is used that wasn't in the cache. I'm sure this could improve performance, but there is a cost in effort Ermm



At some point, you'll have to get the data you need, it's just a matter of when.



I personally, so far, have just gotten the data when I need it, using ExecuteScalar. I have to say that so far I haven't noticed too much problem with performance. I usually create a custom property in my "orders" bo that calls a method in my "customer" bo, which uses ExecuteScalar. Data access seems pretty fast, even when I do something like to to fill a grid or listbox. 99% of my users are remote and we're using ES. I'm sure I have some optimization in my future, but less than I would have thought! BigGrin



Hope these thoughts are a help!
By StrataFrame Team - 11/19/2007

You would need to overload the GetCustomerType() method to allow you to pass a parameter that would tell whether it can use database access.  So, if you call GetCustomerType(false) and you have all the information you need in memory, then it won't need to connect to the database again, just return the cached value.  Otherwise, if you don't have the data already retrieved then you're still going to probably need to retrieve the value from the database.