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