Tutorial - Generating a sample repository-pattern
test application with CodeTrigger
To work with these sample projects you will need CodeTrigger installed, Visual Studio
2013-2017, and a test database with some data.
Follow these steps below to generate a multi-tier (testclient/businesslayer/datalayer)
application using the repository pattern
This guide has been updated for version 5.1.0.0 (released June 10th 2017)
|
|
Microsoft Northwind Sample db
|
Step 1 - Ensure you have a relevant test database
The CodeTrigger sample applications are designed to work with your existing database
schema to ensure that the samples are as relevant as possible. Ensure that you have
a TEST SQL Server/Oracle/MYSQL database handy. CodeTrigger and its associated supplier
companies do not accept any liability for data loss whilst using the CodeTrigger
product. It is important that you use a test database until you are familiar with
the functionality of the generated code.
|
|
Step 2 - Create a new CodeTrigger project
Create a new Multi-tier application using the wizard. As a guide you can use the 'DB to Microservice' wizard. Name your project SampleRepositoryPattern
and generate your application as usual, using CodeTrigger.
|
|
|
Step 3 - Choose the following settings in the Advanced options tab
Generate interface definitions: Ticked
Generate using repository pattern: Ticked
Generate data versioning and concurrency management: Ticked
and in the schema objects tab, select the schema objects you are interested in generating code for
|
|
Step 4 - Generate the business objects
Click on the 'Business Objects' tab to generate the domain objects and structures and relationships. Select the business objects you are interested in generating code for
|
|
Step 5 - Shoot!
Click on the 'Generate Code' button to generate the required code.
Because in this tutorial we selected the 'Generate data versioning and concurrency management' advanced option, the wizard may generate a script and prompt you to run that script against your database.
This script will create the _ctVersion column on your chosen table(s), which CodeTrigger uses to manage concurrency issues.
The test below tests the concurrency aspect (causes an expected concurrency failure).
However if you do not wish to add this column to your database tables, you can uncheck the concurrency option above, and regenerate the code. However you will need to rewrite the test below to evaluate some other apect of the expected behaviour.
|
|
|
|
Step 6 - Create a new test client project using Visual Studio 2013-2017
Within the same Visual Studio solution, create a new 'Test' client project
at an accessible location on your local hard drive. For the purposes of this sample,
we will assume the following project settings:
Project Name: SampleRepositoryPattern.Tests
Project Default Namespace: SampleRepositoryPattern.Tests
Project Location: C:\CodeTriggerSamples\SampleRepositoryPattern\
In this test client project, if Visual studio has not generated an App.config file
for you, you may have to add it yourself, via 'visual studio->add->new item->general->application
configuration file' context menu items
|
|
Right click on the solution in Visual studio and 'Build Solution', ensure all the
Visual Studio generated projects and code in the solution builds successfully.
|
|
Step 7 - Configure a test & RUN!
Now we create a basic test to demonstrate the usage of the generated code (repository
pattern).
Note that this is not a tutorial on writing Unit tests! In particular, to keep things
short we have put a lot of tests into the same test function which you certainly
should not do when writing your own unit tests.
In the SampleRepositoryPattern.Tests project you created in step 5, add a reference
to the SampleRepositoryPattern.Business project.
In the SampleRepositoryPattern.Data project folder you will also find a
'generated.config' file [C:\CodeTriggerSamples\SampleRepositoryPattern\SampleRepositoryPattern.Data\generated.config]
that contains additional configuration information for your application, including
database connection information.
Copy the appSettings section in this file to the config section in your SampleRepositoryPattern.Tests
project config file (App.config).
Thats it, you are ready to consume the business and data layer via your repository
pattern.
In the UnitTest1 class that was generated by Visual Studio, add the following using
namespace declarations:
using SampleRepositoryPattern.Business;
using SampleRepositoryPattern.Business.Interfaces;
using SampleRepositoryPattern.Business.Repository;
using SampleRepositoryPattern.Business.Repository.Interfaces;
You can then prep your business layer objects with the required repository like
so:
var repoFactory = RF.New();
ICategoriesRepository iDAOCategoriesRepository = (ICategoriesRepository)repoFactory.CategoriesRepository;
BOCategories boCategory = new BOCategories();
boCategory.CategoriesRepository = iDAOCategoriesRepository;
The code below shows a test which:
- creates and saves a new category object
- gets the identity id issued by the database
- checks that the version of the object in the db is 0
- updates the object and saves to the db
- checks that the version in the db has incremented to 1
- deletes the object
- checks that the object can no longer be instantiated/initialized
Of course each one of these items would normally be a test in itself, we are just
presenting them together in this one big test to simplify this tutorial.
And thats it, you have successfully created and unit tested a multi-tier, database
enabled, repository pattern based application with concurrency and versioning features
built in, using CodeTrigger.
|
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SampleRepositoryPattern.Business;
using SampleRepositoryPattern.Business.Interfaces;
using SampleRepositoryPattern.Business.Repository;
using SampleRepositoryPattern.Business.Repository.Interfaces;
namespace SampleRepositoryPattern.Tests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void create_update_delete_Category()
{
string initialName = "My Test Category";
string initialDescription = "initial desc";
string updatedDescription = "updated desc";
//setup the test using a repository
var repoFactory = RF.New();
ICategoriesRepository iDAOCategoriesRepository = (ICategoriesRepository)repoFactory.CategoriesRepository;
BOCategories boCategory = new BOCategories();
boCategory.CategoriesRepository = iDAOCategoriesRepository;
try
{
//test saving a new category
boCategory.CategoryName = initialName;
boCategory.Description = initialDescription;
boCategory.SaveNew();
//test#1 that the versioning is working properly, here the version should be 0 when we load
int categoryID = (int)boCategory.CategoryID;
boCategory.Init(categoryID);
Assert.AreEqual(boCategory.CtrVersion, 0);
//test updating an existing category
boCategory.Description = updatedDescription;
boCategory.Update();
boCategory.Init(categoryID);
Assert.AreEqual(boCategory.Description, updatedDescription);
//test#2 that the concurrency & versioning is working properly, here the incremented version should be 1
//after the previous update
Assert.AreEqual(boCategory.CtrVersion, 1);
//test that we can delete
boCategory.Delete();
try
{
boCategory.Init(categoryID);
Assert.Fail("Test failed, object has been deleted and should no longer exist");
}
catch (Exception ex)
{
//test passed because we are expecting this exception as we are trying to initialise
//with an id belonging to an object that no longer exists (since we deleted it above)
StringAssert.Contains(ex.Message, "Object reference");
}
}
catch
{
//catch all to try and get rid of this test category so we can run this test again
boCategory.Delete();
}
}
}
}
|
|