Delphi style: How to structure data modules for unit-testable code?

后端 未结 4 994
余生分开走
余生分开走 2021-02-04 12:26

I am looking for some advice about structuring Delphi programs for maintainability. I\'ve come to Delphi programming after a couple of decades of mostly C/C++ though I first lea

4条回答
  •  后悔当初
    2021-02-04 12:32

    I think you need (and in fact, most delphi database developers are going to need) a Mock Dataset (Query, table, etc etc) Component that you could use, and substitute them at module-init time, for your current ADO dataset objects to this mock dataset, for test purposes. Instead of forcing Interfaces into your design, which are one way to provide a substitution capability, consider the fact that by Liskov substitution principle, you should be able to (at test fixture setup time), inject into your data module, the set of mock-datasets that you want to use, and simply replace the ADO datasets that you are using, at test execution time, with some other functionally equivalent entity (a mock dataset, or a file-backed table dataset).

    Perhaps you could even remove the datasets completely from the data module, and have them hooked up at runtime (in your main application) to the correct ADO dataset objects, and in unit tests, attach your mock datasets.

    Since you did not write the ADO dataset, you don't need to unit test it. However, mocking up such a dataset might be difficult.

    I would suggest you consider using a JvCsvDataSet or a ClientDataSet as the basis for your fixture (mock) datasets. You would be able to then use these to make sure that all your database platform dependencies (stuff that writes remote procedures or database SQL) is abstracted out into other classes, which again you are going to have to mock up. Such an effort might not only be required to make your business logic unit testable, it might also be a step towards becoming multiple-database-platform friendly in your business logic.

    imagine you have an ADOQuery called CustomerQuery, rename the object that you dropped onto your data module, to CustomerQueryImpl, and add this to your data module class declaration:

      private
            FCustomerQuery:TADOQuery;
    
      published
            property CustomerQuery:TADOQuery read FCustomerQuery write FCustomerQuery;
    

    then in your data module on create event, hook up the property to the objects:

       FCustomerQuery := CustomerQueryImpl
    

    Now you can write unit tests, which will 'hook' in and replace CustomerQuery with its own test fixture (mock object) at runtime.

提交回复
热议问题