Given propFns as an array of Expression<Func<T, string>> and string str, you can do:
var ansParam = propFns[0].Parameters[0];
var newBody = propFns.Select(f => (Expression)Expression.Call(
                                        ReplacingExpressionVisitor.Replace(f.Parameters[0], ansParam, f.Body),
                                        typeof(String).GetMethod("Contains", new[] { typeof(String) }),
                                        Expression.Constant(str))
              ).Aggregate(Expression.OrElse);
var newLambda = Expression.Lambda<Func<TestClass,bool>>(newBody, ansParam);
NOTE: If you are not using EF Core, and don't have ReplacingExpressionVisitor available, you can use your own version:
/// <summary>
/// Replaces an Expression (reference Equals) with another Expression
/// </summary>
/// <param name="orig">The original Expression.</param>
/// <param name="from">The from Expression.</param>
/// <param name="to">The to Expression.</param>
/// <returns>Expression with all occurrences of from replaced with to</returns>
public static T Replace<T>(this T orig, Expression from, Expression to) where T : Expression => (T)new ReplaceVisitor(from, to).Visit(orig);
/// <summary>
/// ExpressionVisitor to replace an Expression (that is Equals) with another Expression.
/// </summary>
public class ReplaceVisitor : ExpressionVisitor {
    readonly Expression from;
    readonly Expression to;
    public ReplaceVisitor(Expression from, Expression to) {
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node) => node == from ? to : base.Visit(node);
}