Codechef4u is a community for computer professionals,by computer professionals,just like you; who loves sharing and helping each others,Join them
Share your post

Creating Unit Tests with C#

Creating Unit Tests using C# and Visual Studio

Creating C4ShopDataValidation Library project for product data validation

Steps:

1. Open Visual Studio.

2. On the File menu=> New=>click Project.

3. New Project dialog box appears.

4. Installed Templates=> click Visual C#.

5. In the list of application types, click Class Library.

6. In Name box, type “C4ShopDataValidation” and then click OK.

Example:

Sample methods under test

   public bool ValidateProductame(ProductProduct)
        {
            if (string.IsNullOrEmpty(Product.ProductName))
                returnfalse;
 
            returntrue;
        }
 

 

public bool ValidatePrductNameWithSpecialChar(Product Product,out string ErrorMessage)
        {
            var regexItem = new Regex("^[a-zA-Z0-9 ]*$");
            if (regexItem.IsMatch(Product.ProductName))
            {
                ErrorMessage = "Special characters not allowed";
                return false;
            }
            ErrorMessage = "";
            return true;
        }

 

Create C4Test Project for unit testing:

Steps:

1.  File menu=>Add=> New Project .

2.  New Project dialog box=> expand Installed=>expand Visual C#=>Test.

3.  Appears list of templates=>select Unit Test Project.

4.  In the Name box, enter BankTest, and then choose OK.

5.  Provide nem “C4Test” now project is added to the the C4Shop solution.

6.  In the C4Test project, add required references i.e  C4ShopDataValidation,BusnessEntities.

7.  Rename existing Class Class.1 or Add new if you want

8.  Start writing test cases.

Example:

 Unit test methods for product name validation   


   [TestClass]
    public class ProductDataValidationTests
    {
 
       //Declaration
        private IProductDataValidation _ProductValidation;
 
 
        //initalize
        [TestInitialize]
        public void ProductDataValidationInitialise()
        {
       
            _ProductValidation = new ProductDataValidation();
 
        }
 
 
        #region Sad Path
 
       
        [TestMethod]
        public void ChaekEmptyProductName()
        {
            var target = _ProductValidation;
            var product = new Product()
            {
                ProductName = "",
                Price = 115,
                Category = new ProductCategory()
              {
                  CategoryName = "Book"
              },
                ImageUrl = @"C:/data"
 
            };
            Assert.IsFalse(target.ValidateProductame(product));
 
        }
 
        [TestMethod]
        public void ChaekBadProductNameForSpecialChar()
        {
            string ExpectedErroMessage = "Special characters not allowed";
            string TargetMessage;
            var target = _ProductValidation;
            var product = new Product()
            {
                ProductName = "CodeChef4u ) SQL rcipies",
                Price = 500,
                Category = new ProductCategory()
                {
                    CategoryName = "Book"
                },
                ImageUrl = @"C:/data"
 
            };
            var isFailed=target.ValidatePrductNameWithSpecialChar(product,out TargetMessage);
            Assert.AreEqual(ExpectedErroMessage, TargetMessage);
        }
    }

 

 

Return output parameter from Stored Procedure

Return output parameter from Stored Procedure in C#

In this Beginner level article I will explain how to use and return value from Stored Procedure using Output Parameter in C#.

In following example stored procedure checks for existing record If found it will return one parameter continue with value 1 and stop inserting any new product.

Example:

Your stored procedure:

-- =============================================
-- Author:                     Nagnath Kendre
-- Create date: <Create Date,,>
-- Description: Add uniqe product data
-- =============================================
CREATE PROCEDURE InsertProducts_SP
            -- Add the parameters for the stored procedure here
       @ProductName [nvarchar](100),
             @UnitPrice float,
       @CategoryID int,
       @Continue int OUTPUT
AS
BEGIN
 
    DECLARE @ChkRecordExist INT
            SELECT @ChkRecordExist=COUNT(ID) FROM Products
            WHERE ProductName=@ProductName and CategoryID=@CategoryID
            IF @ChkRecordExist=0
            BEGIN
           
    SELECT @Continue = 0
 
     --insert query here
     INSERT INTO Products
           (
            [ProductName] ,
            [Description],
            [UnitPrice],
            [CategoryID])
VALUES
( @ProductName,'',@UnitPrice,@CategoryID)
 
  END
 
  ELSE
  BEGIN
            SELECT @Continue = 1
  END
END
GO

 

C# Code:

        /// <summary>
        /// inserts a new Products.
        /// </summary>
        public bool CreateProducts (Product product)
        {
            //protection code
            if (product == null) return false;
            var dbcommand = _sQlClientFactory.CreateCommand();
            // Create
            dbcommand.CommandType = CommandType.StoredProcedure;
            dbcommand.CommandText = "InsertProducts_SP";
 
            dbcommand.Parameters.Add(new SqlParameter("@ProductName",  product.Name));
 
            dbcommand.Parameters.Add(new SqlParameter("@Price", product.Price));
 
            dbcommand.Parameters.Add(new SqlParameter("@CategoryId", product.Category));
           
 
            //adding output parameter as preventive reason
            //if found record no need to add proceed for update
            SqlParameter outParamter = new SqlParameter();
            outParamter.ParameterName = "@Continue";
            outParamter.Direction = System.Data.ParameterDirection.Output;
            outParamter.DbType = System.Data.DbType.Int32;
            dbcommand.Parameters.Add(outParamter);
 
            var isInserted=ExecuteTransaction(dbcommand);
 
            var countinueUpdate = Convert.ToInt32(outParamter.Value);
            if (countinueUpdate == 1)
            { ContinueUpdate = true;
            }
            return isInserted;
            }

 

public bool ExecuteTransaction(IDbCommand Command)
        {
            var status = false;
                using (var myCon= SqlClient.CreateConnection(connString))
                {
                    myCon.Open();
 
                    using (Command)
                    {
                        Command.Connection = myCon;
                      
                        var rowsAffected = Command.ExecuteNonQuery();
                        if (rowsAffected >= 1)
                        {
                            Command.Transaction.Commit();
                            status = true;
                        }
                        else
                        {
                            Command.Transaction.Rollback();
                        }
                    }
                }
            }
         }

          

TransactionScope The transaction has aborted.

TransactionScope Error:The transaction has aborted.

This error you may face in two conditions

 1. Time out condition.

 2.  Inside scope other command transaction failing or rollbacks.

Solution:

Timeout Exception:

You can resolve timeout condition issue increasing transaction scope timeout and

Ensure timeout of the transaction scope is longer than the command timeout.

var option = new TransactionOptions
                    {
IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted,
                        Timeout = TimeSpan.FromSeconds(90)
                    };


myContext.CommandTimeout
= 60; //This is seconds

Inner command transaction failing:

Logical insert failing:

With following example in insert logic what if insert store procedure has some Logic that prevents duplicate records insertion if new records then only insert Records (if else used).
In this scenario logically insert is not failing but command.ExecuteNonQuery will return Result 0 and command rollbacks transaction.
You can avoid this by passing output parameter and set parameter value as continue update that will resolve your issue.

Inner exception:

Another scenario is that what if toy get exception inside scope for sub process , you can pass it to parent exception and process for next update that will resolve your issue.
  try
        {
            using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
            {
                // insert logic
                try
                {
                    using (var conn = GetConnection())
                    {
                                string query =
                  @" insert Quiery"
 
                       using (var command = new SqlCommand(query, conn))
                        var rowsAffected = Command.ExecuteNonQuery();
                        if (rowsAffected >= 1&&ContinueUpate==1)
                        {
                            Command.Transaction.Commit();
                            status = true;
                        }
                        else
                        {
                            Command.Transaction.Rollback();
                        }
                    }
                }
                catch (SqlException ex)
                {
                    // log your exception
                    throw// re-throw exception
                }
 
               // update logic
                try
                {
                    using (var conn = GetConnection())
                    {
                          string query = @" Delete Quiery"
                    }
                }
                catch (SqlException ex)
                {
                    // log your exception
                    throw// re-throw exception
                }
                scope.Complete();
            }
        }
     // this catch block will resolve your issue
        catch (TransactionAbortedException ex)
        {
            //you can log here internal exception if you want  
        }