TestValueFactory C# & Mapper Tests

When you’re writing tests, especially mapper tests, knowing the value which is mapped is not of great use. What you’re testing is that the value is correctly mapped, or bound to the accurate location in destination.

Mapping is very often not considered by young developer (and sometimes senior developer) as a source of error. In my opinion, actually it is. Thus, that’s why I am sharing those code snippets to help people writing tests on mappers.

Keep this sentence in mind, when writing tests in group code project : “Backup your a** !”. Everything can be a source of error.

The TestValueHelper implementation provide issue resolution to handle random type value generation. This class is certainly to be developped.

using System;
using System.Collections.Generic;

namespace maximilienzakowski.com.TestToolKit
{
    public static class TestValueFactory
    {
        private static readonly Random _random = new Random();

        public static int GetRandomIntValue()
        {
            return _random.Next();
        }

        public static int GetRandomIntValue(int minValue, int maxValue)
        {
            return _random.Next(minValue, maxValue);
        }

        public static int GetRandomIntValue(int[] except)
        {
            var exceptSet = new HashSet<int>(except??new int[] { });
            int result;
            do
            {
                result = _random.Next();
            }
            while (exceptSet.Contains(result));
            return result;
        }

        public static DateTime GetRandomDateTimeValue()
        {
            DateTime start = new DateTime(1970, 1, 1);
            int range = (DateTime.Today - start).Days;
            return start.AddDays(_random.Next(range))
                .AddHours(_random.Next(0, 24))
                .AddMinutes(_random.Next(0, 60))
                .AddSeconds(_random.Next(0, 60));
        }

        public static double GetRandomDoubleValue()
        {
            return _random.Next() * _random.NextDouble();
        }

        public static decimal GetRandomDecimalValue()
        {
            double RandH, RandL;
            do
            {
                RandH = _random.NextDouble();
                RandL = _random.NextDouble();
            } while ((RandH > 0.99999999999999d) || (RandL > 0.99999999999999d));
            return (decimal)RandH + (decimal)RandL / 1E14m;
        }
        public static decimal GetRandomDecimalValue( decimal minValue, decimal maxValue)
        {
            return GetRandomDecimalValue() * (maxValue - minValue) + minValue;
        }

        public static T GetRandomEnumValue<T>() where T : System.Enum
        {
            var values = Enum.GetValues(typeof(T));
            return (T)values.GetValue(_random.Next(0,values.Length-1));
        }

        public static string GetRandomStringValue()
        {
            return GetRandomStringValue(20);
        }

        public static string GetRandomStringValue(int length)
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            return new string(Enumerable.Repeat(chars, length).Select(s => s[_random.Next(s.Length)]).ToArray());
        }
    }
}

Tested code snippet which is a builder + mapper association :

public class ItemToInvoiceRowConverter2
    {
        public IInvoiceRow Convert(IItem converted)
        {
            if (converted == null) return null;
            var result = new InvoiceRow();
            //result.Number = converted.Id;
            result.IdItem = converted.Id;
            result.Kind = converted.Kind;
            result.Label = converted.Name;
            //result.Vat = converted.;
            result.Unit = converted.Unit;
            result.UnitPrice = converted.Price;
            //result.Discount = converted.Id;
            //result.Quantity = converted.Id;
            return result;
        }
    }

Unit test code :

using myApplication.Converters;
using myApplication.Models;
using maximilienzakowski.com.TestToolKit;
using Moq;
using NUnit.Framework;

namespace myApplication.Tests
{
    [TestFixture]
    public class ItemToInvoiceRowConverterTests
    {
        private ItemToInvoiceRowConverter2 BuildTested()
        {
            return new ItemToInvoiceRowConverter2();
        }

        [Test]
        public void ConvertShouldReturnNullWhenConvertedIsNull()
        {
            var tested = BuildTested();
            var result = tested.Convert(null);
            Assert.IsNull(result);
        }


        [Test]
        public void ConvertShouldConvertAndMapAccurately()
        {
            var converted = new Mock<IItem>();
            var id = TestValueFactory.GetRandomIntValue();
            var kind = TestValueFactory.GetRandomStringValue();
            var name = TestValueFactory.GetRandomStringValue();
            var unit = TestValueFactory.GetRandomStringValue();
            var price = TestValueFactory.GetRandomDecimalValue();

            converted.SetupGet(x => x.Id).Returns(id);
            converted.SetupGet(x => x.Kind).Returns(kind);
            converted.SetupGet(x => x.Name).Returns(name);
            converted.SetupGet(x => x.Unit).Returns(unit);
            converted.SetupGet(x => x.Price).Returns(price);
            var tested = BuildTested();
            var result = tested.Convert(converted.Object);
            Assert.IsNotNull(result);
            Assert.AreEqual(id, result.IdItem);
            Assert.AreEqual(kind, result.Kind);
            Assert.AreEqual(name, result.Label);
            Assert.AreEqual(unit, result.Unit);
            Assert.AreEqual(price, result.UnitPrice);

            converted.VerifyGet(x => x.Id,Times.Once);
            converted.VerifyGet(x => x.Kind, Times.Once);
            converted.VerifyGet(x => x.Name, Times.Once);
            converted.VerifyGet(x => x.Unit, Times.Once);
            converted.VerifyGet(x => x.Price, Times.Once);
            converted.VerifyNoOtherCalls();
        }
    }
}

Hope this will help someone else than me…

Linq.Net To SqlLite Converter implementation attempt

Sometimes when you want to manage your code efficiency you may need to optimize some .Net implementation.

Instead of relying on Entity Framework or other closed binary implementation you may need to implement your specific AdHoc behavior, this is a good example to do so…

Underneath you will find my proposal to implement a Linq to SQLLite conversion with C#. This is a generic code and may be optimized in many way for your implementation needs. It use System.Linq but remediation can be done very easily to not depend on this library.

using System.Collections;
using System.Linq.Expressions;
using System.Reflection;

namespace Com.Maximilienzakowski.Dal.Common.Repository
{
    public interface ICommandTextWhereArgBuilder<T> where T : class
    {
        string Build(Expression<Func<T, bool>> whereExpression);
        string Build(Expression node);
    }

    public class SqliteCommandTextWhereArgBuilder<T> : ICommandTextWhereArgBuilder<T> where T : class
    {
        private readonly IDictionary<ExpressionType,ISqlLiteWhereCommandExpressionBuilder> _whereExpressionsBuilders;
        private readonly IObjectToSqlValueConverter _objectToSqlValueConverter = new ObjectToSqlValueConverter();
        public SqliteCommandTextWhereArgBuilder()
        {
            var sqlLiteWhereCommandExpressionBuilders = new ISqlLiteWhereCommandExpressionBuilder[]
            {
                new SqlLiteLambdaWhereCommandExpressionBuilder<T>(this),
                new SqlLiteAndWhereCommandExpressionBuilder<T>(this),
                new SqlLiteAndAlsoWhereCommandExpressionBuilder<T>(this),
                new SqlLiteEqualWhereCommandExpressionBuilder<T>(this),
                new SqlLiteContainsCallWhereCommandExpressionBuilder<T>(this),
                new SqliteConvertAccessWhereCommandExpressionBuilder<T>(this),
                new SqliteMemberAccessWhereCommandExpressionBuilder<T>(_objectToSqlValueConverter),
                new SqliteConstantWhereCommandExpressionBuilder<T>(_objectToSqlValueConverter),
                
            };
            _whereExpressionsBuilders = sqlLiteWhereCommandExpressionBuilders.ToDictionary(m => m.ExpressionType, m => m);
        }


        public string Build(Expression<Func<T, bool>> whereExpression)
        {
            var expression = whereExpression.Reduce;
            return Build(expression());
        }

        public string Build(Expression node)
        {
            if(!_whereExpressionsBuilders.TryGetValue(node.NodeType, out var whereExpressionBuilder)) return "UNDEFINED EXPRESSION BUILDER";
            return whereExpressionBuilder.Build(node);
        }
    }

    public class SqlLiteContainsCallWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {
        private readonly ICommandTextWhereArgBuilder<T> _commandTextWhereArgBuilder;
        public ExpressionType ExpressionType => ExpressionType.Call;
        public SqlLiteContainsCallWhereCommandExpressionBuilder(ICommandTextWhereArgBuilder<T> commandTextWhereArgBuilder)
        {
            _commandTextWhereArgBuilder = commandTextWhereArgBuilder ?? throw new ArgumentNullException(nameof(commandTextWhereArgBuilder));
        }
        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType.Call) return string.Empty;
            var methodCallNode = (MethodCallExpression)node;
            if (methodCallNode.Method.Name != "Contains") return "UNHANDLED METHOD CALL";
            if(methodCallNode.Arguments.Count == 2)
            {
                return $"({ _commandTextWhereArgBuilder.Build(methodCallNode.Arguments.Last())} IN {_commandTextWhereArgBuilder.Build(methodCallNode.Arguments.First())})";
            }
            else if(methodCallNode.Arguments.Count == 1)
            {
                var left = _commandTextWhereArgBuilder.Build(methodCallNode.Arguments.Single());
                return $"({left} IN {_commandTextWhereArgBuilder.Build(methodCallNode.Object)})";
            }
            return "UNHANDLED CONTAINS METHOD CALL";
        }
    }


    public class SqlLiteLambdaWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {
        private readonly ICommandTextWhereArgBuilder<T> _commandTextWhereArgBuilder;
        public ExpressionType ExpressionType => ExpressionType.Lambda;
        public SqlLiteLambdaWhereCommandExpressionBuilder(ICommandTextWhereArgBuilder<T> commandTextWhereArgBuilder)
        {
            _commandTextWhereArgBuilder = commandTextWhereArgBuilder ?? throw new ArgumentNullException(nameof(commandTextWhereArgBuilder));
        }
        public string Build(Expression? node)
        {
            if(node.NodeType != ExpressionType.Lambda) return string.Empty;
            var lambdaNode = (LambdaExpression)node;
            return _commandTextWhereArgBuilder.Build(lambdaNode.Body);
        }
    }

    public class SqlLiteAndWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {
        private readonly ICommandTextWhereArgBuilder<T> _commandTextWhereArgBuilder;

        public ExpressionType ExpressionType => ExpressionType.And;
        public SqlLiteAndWhereCommandExpressionBuilder(ICommandTextWhereArgBuilder<T> commandTextWhereArgBuilder)
        {
            _commandTextWhereArgBuilder = commandTextWhereArgBuilder ?? throw new ArgumentNullException(nameof(commandTextWhereArgBuilder));
        }

        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType) return string.Empty;
            var binaryExpressionType = (BinaryExpression)node;
            return $"({_commandTextWhereArgBuilder.Build(binaryExpressionType.Left)}) AND ({_commandTextWhereArgBuilder.Build(binaryExpressionType.Right)})";
        }
    }

    public class SqlLiteAndAlsoWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {
        private readonly ICommandTextWhereArgBuilder<T> _commandTextWhereArgBuilder;

        public ExpressionType ExpressionType => ExpressionType.AndAlso;
        public SqlLiteAndAlsoWhereCommandExpressionBuilder(ICommandTextWhereArgBuilder<T> commandTextWhereArgBuilder)
        {
            _commandTextWhereArgBuilder = commandTextWhereArgBuilder ?? throw new ArgumentNullException(nameof(commandTextWhereArgBuilder));
        }

        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType) return string.Empty;
            var binaryExpressionType = (BinaryExpression)node;
            return $"({_commandTextWhereArgBuilder.Build(binaryExpressionType.Left)}) AND ({_commandTextWhereArgBuilder.Build(binaryExpressionType.Right)})";
        }
    }

    public class SqlLiteEqualWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {
        private readonly ICommandTextWhereArgBuilder<T> _commandTextWhereArgBuilder;

        public ExpressionType ExpressionType => ExpressionType.Equal;
        public SqlLiteEqualWhereCommandExpressionBuilder(ICommandTextWhereArgBuilder<T> commandTextWhereArgBuilder)
        {
            _commandTextWhereArgBuilder = commandTextWhereArgBuilder ?? throw new ArgumentNullException(nameof(commandTextWhereArgBuilder));
        }

        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType) return string.Empty;
            var binaryExpressionType = (BinaryExpression)node;
            return $"{_commandTextWhereArgBuilder.Build(binaryExpressionType.Left)} = {_commandTextWhereArgBuilder.Build(binaryExpressionType.Right)}";
        }
    }

    public class SqliteMemberAccessWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {

        private readonly IObjectToSqlValueConverter _objectToSqlValueConverter;
        public ExpressionType ExpressionType => ExpressionType.MemberAccess;
        public SqliteMemberAccessWhereCommandExpressionBuilder(IObjectToSqlValueConverter objectToSqlValueConverter)
        {
            _objectToSqlValueConverter = objectToSqlValueConverter ?? throw new ArgumentNullException(nameof(objectToSqlValueConverter));
        }

        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType) return string.Empty;
            var memberExpression = (MemberExpression)node;
            if(memberExpression.Member.MemberType == MemberTypes.Field)
            {
                if(memberExpression.Expression == null) return "NULL UNDERLYING EXPRESSION IN MEMBER EXPRESSION";
                if (memberExpression.Expression.NodeType != ExpressionType.Constant) return "NOT A CONSTANT EXPRESSION NODE TYPE IN MEMBER EXPRESSION";
                var constantExpression = (ConstantExpression)memberExpression.Expression;
                var fieldInfo = (FieldInfo)memberExpression.Member;
                return $"\"{_objectToSqlValueConverter.Convert(fieldInfo.GetValue(constantExpression.Value))}\"";
            }
            return $"\"{memberExpression?.Member?.Name}\"";
        }
    }

    public class SqliteConvertAccessWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {

        private readonly ICommandTextWhereArgBuilder<T> _commandTextWhereArgBuilder;
        public ExpressionType ExpressionType => ExpressionType.Convert;
        public SqliteConvertAccessWhereCommandExpressionBuilder(ICommandTextWhereArgBuilder<T> commandTextWhereArgBuilder)
        {
            _commandTextWhereArgBuilder = commandTextWhereArgBuilder ?? throw new ArgumentNullException(nameof(commandTextWhereArgBuilder));
        }

        private static readonly IDictionary<Tuple<Type, Type>, string> _formatBySourceAndDestinationTupleTypes =
            new Dictionary<Tuple<Type, Type>, string>()
            {
                {Tuple.Create(typeof(int),typeof(long)), "{0}" },
            };

        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType) return string.Empty;
            var unaryExpression = (UnaryExpression)node;
            if (!_formatBySourceAndDestinationTupleTypes.TryGetValue(Tuple.Create(unaryExpression.Operand.Type, unaryExpression.Type), out var format))
                return "UNKNONW CONVERT EXPRESSION";
            return string.Format(format, _commandTextWhereArgBuilder.Build(unaryExpression.Operand));
        }
    }

    public class SqliteConstantWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {
        private readonly IObjectToSqlValueConverter _objectToSqlValueConverter1;
        public ExpressionType ExpressionType => ExpressionType.Constant;
        public SqliteConstantWhereCommandExpressionBuilder(IObjectToSqlValueConverter objectToSalValueConverter)
        {
            _objectToSqlValueConverter1 = objectToSalValueConverter ?? throw new ArgumentNullException(nameof(objectToSalValueConverter));
        }

        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType) return string.Empty;
            var constantExpression = (ConstantExpression)node;
            return _objectToSqlValueConverter1.Convert(constantExpression.Value);
        }
    }

    


    public class ObjectToSqlValueConverter : IObjectToSqlValueConverter
    {
        private readonly IDictionary<Type, Func<object, string>> _valueConversionFuncByType =
            new Dictionary<Type, Func<object, string>>()
            {
                {typeof(string), value => $"'{value}'"},
                {typeof(int), value => $"{value}"},
                {typeof(long), value => $"{value}"},
                {typeof(short), value => $"{value}"},
                {typeof(float), value => $"{value}"},
                {typeof(double), value => $"{value}"},
                {typeof(decimal), value => $"{value}"},
            };
        public string Convert(object? value)
        {
            if (value == null) return "NULL";
            var valueType = value.GetType();
            if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                var underlyingValueType = Nullable.GetUnderlyingType(valueType);
                if (underlyingValueType == null) return "UNKNOWN CASE OF NULLABLE UNDERLYING NULL VALUE";
                return Convert(System.Convert.ChangeType(value, underlyingValueType));
            }
            if((valueType.IsArray || valueType.IsGenericType && valueType.GetGenericTypeDefinition().IsAssignableTo(typeof(IEnumerable))))
            {
                var enumerable = (IEnumerable)value;
                return $"({string.Join(",", Enumerate(enumerable).Select(Convert))})";
            }
            if (!_valueConversionFuncByType.TryGetValue(valueType, out var conversionFunc)) return "UNKNOWN TYPE";
            return conversionFunc(value);
        }

        private IEnumerable<object> Enumerate(IEnumerable enumerable)
        {
            foreach(var value in enumerable)
            {
                yield return value;
            }
        }
    }
}

PinkFlower.fr

Pinkflower.fr is a website of a massage parlour which aims to get persons rid of stress and improve their well beings. They propose a large range of massage which are all of great quality.

This massage parlour is located in Plessis-Bouchard (Postal code : 95130), France

I helped in this project to :

  • Design the website
  • Setup the website
  • Choose and setup scheduling functionality
  • Setup the galleries
  • Setup SEO (Search Engine Optimization) in order to have the website well referenced.

You can visit the website at : https://www.pinkflower.fr/

Pinkflower main page

Energia – Analiza – Urządzenia

I actively collaborated with Tomasz SZYMANSKI in order to help him to set up his website.

This website give you advise, definitions and propose you devices in order to measure and benefit from different kind of energy advantages.

Website url : https://energia-orgonu.com/

Screen shot of the Energia – Analyza – Urządzenia website.

Database Template Handler Project

As the ORMs (Object Relational Model) are now very used in the computer development project in order to manage interfacing between systems, the DB Template Handler project is an atempt to solve the issue of the heterogeneity between languages that you interface in your data access layout.

The Project try to create a devoted semantic and language basic functionality to manage the generation of every file suitable to database or other DAL interfacing.

Image

The project page :

https://github.com/cosXsinX/DBTemplateHanlder-NetCore3

Jointure implementation in C#

Sometimes when you want to manage your code efficiency you may need to optimize some .Net implementation.

Jointure implementation in C# may be such a case.

Underneath you will find my proposal to implement a jointure in C# environment. This is a generic code and may be optimized in many way for your implementation needs. It use System.Linq but remediation can be done very easily to not depend on this library.

using System;
using System.Collections.Generic;
using System.Linq;

namespace org.maximilienzakowski.Jointures
{
    public static class Extensions
    {
        public static TJ[] InnerJoin<TL, TR, TK, TJ>(this IEnumerable<TL> lefts, IEnumerable<TR> rights, Func<TL, TK> onLeftKey, Func<TR, TK> onRightKey,
           Func<TL, TR, TJ> jointureBuilder)
        {
            var leftsWithKeys = lefts.Select(l => new Tuple<TL, TK>(l, onLeftKey(l)));
            var rightsWithKeys = rights.Select(r => new Tuple<TR, TK>(r, onRightKey(r)));
            var rightGroupsByKey = rightsWithKeys.GroupBy(r => r.Item2, m => m.Item1).ToDictionary(m => m.Key, m => m.ToArray());
            var defaultJoineds = new TR[] { };
            var enumerable = leftsWithKeys.SelectMany(m =>
            {
                TR[] joineds = defaultJoineds;
                if (m.Item2 != null)
                {
                    rightGroupsByKey.TryGetValue(m.Item2, out joineds);
                }
                return (joineds ?? defaultJoineds).Select(joined => jointureBuilder(m.Item1, joined));
            });
            return enumerable.ToArray();
        }
        public static Tuple<TL,TR>[] LeftJoin<TL,TR,TK>(this IEnumerable<TL> lefts, IEnumerable<TR> rights, Func<TL,TK> onLeftKey, Func<TR,TK> onRightKey)
        {
            return LeftJoin(lefts, rights, onLeftKey, onRightKey, (left, right) => new Tuple<TL, TR>(left, right), default(TR));
        }

        public static Tuple<TL,TR>[] LeftJoin<TL,TR,TK>(this IEnumerable<TL> lefts, IEnumerable<TR> rights,
            Func<TL,TK> onLeftKey, Func<TR,TK> onRightKey,TR defaultJoined)
        {
            return LeftJoin(lefts, rights, onLeftKey, onRightKey, (left, right) => new Tuple<TL, TR>(left, right), defaultJoined);
        }

        public static IList<TJ> LeftJoin<TL,TR,TK,TJ>(this IEnumerable<TL> lefts,IEnumerable<TR> rights, Func<TL,TK> onLeftKey,Func<TR,TK> onRightKey, Func<TL,TR,TJ> jointureBuilder)
        {
            return LeftJoin(lefts, rights, onLeftKey, onRightKey, jointureBuilder, default(TR));
        }

        public static TJ[] LeftJoin<TL,TR,TK,TJ>(this IEnumerable<TL> lefts, IEnumerable<TR> rights, Func<TL,TK> onLeftKey,Func<TR,TK> onRightKey, 
            Func<TL,TR,TJ> jointureBuilder, TR defaultJoined)
        {
            var leftsWithKeys = lefts.Select(l => new Tuple<TL, TK>(l, onLeftKey(l)));
            var rightsWithKeys = rights.Select(r => new Tuple<TR, TK>(r, onRightKey(r)));
            var rightGroupsByKey = rightsWithKeys.GroupBy(r => r.Item2, m => m.Item1).ToDictionary(m => m.Key, m => m.ToArray());
            var defaultJoineds = new TR[] { defaultJoined };
            var enumerable = leftsWithKeys.SelectMany(m =>
            {
                TR[] joineds = defaultJoineds;
                if(m.Item2 != null)
                {
                    rightGroupsByKey.TryGetValue(m.Item2, out joineds);
                }
                return (joineds ?? defaultJoineds).Select(joined => jointureBuilder(m.Item1, joined));
            });
            return enumerable.ToArray();
        }


        public static Tuple<TL,TR>[] FullJoin<TL,TR,TK>(this IEnumerable<TL> lefts, IList<TR> rights,
            Func<TL,TK> leftKeyFunc, Func<TR,TK> rightKeyFunc, TL defaultLeft = default(TL), TR defaultRight = default(TR))
        {
            var leftJoinedToRight =
                lefts.LeftJoin(rights, leftKeyFunc, rightKeyFunc, defaultRight).ToArray();
            var joinedRightKeys =
                new HashSet<TK>(leftJoinedToRight
                    .Where(m => m.Item2 != null)
                    .Select(m => rightKeyFunc(m.Item2)).Distinct());
            var defaultLeftAndMissingRights =
                rights
                    .Select(m => Tuple.Create(m, rightKeyFunc(m)))
                    .Where(m => !joinedRightKeys.Contains(m.Item2))
                    .Select(m => Tuple.Create(defaultLeft, m.Item1)).ToArray();
            var fullJointure = leftJoinedToRight.Concat(defaultLeftAndMissingRights).ToArray();
            return fullJointure;
        }
    }
}