Unit test Case - MissingMethodException - c#

This is method to Convert String[] To String.
private string ConvertStringArrayToString(System.String[] array)
{
string result = string.Join("<br />", array);
return result.ToString();
}
This is unit test case method for the above method.
[TestMethod]
public void ConvertStringArrayToString_shouldReturnString()
{
string returnedString = null;
PrivateObject o = new PrivateObject(typeof(DemoClass));
System.String[] array = new System.String[]
{
"Index0","Index0","Index0","Index0"
};
returnedString = (string)Convert.ChangeType((o.Invoke("ConvertStringArrayToString", array)), typeof(string));
}
This results in missing method exception.
I found the error is in Passing parameter i.e. string[]
But when I replace method access specifier as public, the test case works without error!
Please help why method cannot be able to access when it is private and string[].

I believe the problem is that array is being passed directly as the argument for the object[] parameter, whereas you really want it to be wrapped so it's just the first argument in an array of arguments. So I'd write this:
string[] array = { "Index0", "Index0", "Index0", "Index0" };
object[] args = { array };
var result = o.Invoke("ConvertStringArrayToString", args);
string returnedString = (string) result;
(There's no need to declare returnedString earlier, and you don't need to use Convert.ChangeType - a cast should be fine.)

Related

Passing varying amount of arguments to VBA SubProcedures

I call a few VBA methods from my C# project. This has caused me to repeat code in my project. So I created a C# method for the few that take the same amount of parameters but a few take different amounts. So I thought about a solution, all the parameters that I pass in are strings, so what if I pass in to my C# method a string array, then convert that string array in to individual strings in the VBA subprocedure call. This is what I have:
private static void RunVBAMethod(Excel.Application excelApp, string logFile, string vBAMethod, string [] args, out string errorType)
{
errorType = CSharpError;
var VbaCrashed = excelApp.Run(vBAMethod, ConvertStringArrayToString(args));
if (VbaCrashed != "False")
{
errorType = VBAError;
throw new Exception(VbaCrashed);
}
}
Here is my ConvertArrayToString method:
private static string ConvertStringArrayToString(string[] array)
{
// Concatenate all the elements into a StringBuilder.
StringBuilder builder = new StringBuilder();
foreach (string value in array)
{
builder.Append(value);
builder.Append(',');
}
return builder.ToString();
}
Then I call it like this:
RunVBAMethod(excelApp, LogFile, "CleanMRP", new string[] { CurrentWorkbook.TimePeriod, CurrentWorkbook.Version, RemoveSpace(CurrentWorkbook.ReportType), CurrentWorkbook.MainMRPFilePath + CurrentWorkbook.FileName, HeaderRow.ToString(), CurrentWorkbook.DataPath }, out ExcelCrashed);
When I run it, it crashes on the excelApp.Run line saying Parameter not optional. Is, what I am trying to do even possible? Am I looking at the wrong way to do, if it is? or am I missing something so small?

Returning the new string in the method

I'm newbie to c#, So i tried the below program, which will change the case of the first character of the string
public class StringBuilder
{
public static string ChangeFirstLetterCase(string inputdata)
{
if(inputdata.Length > 0)
{
char[] charArray = inputdata.ToCharArray();
charArray[0] = char.IsUpper(charArray[0]) ?
char.ToLower(charArray[0]) : char.ToUpper(charArray[0]);
//return new string(charArray);
return charArray.ToString();
}
return inputdata;
}
}
class Program
{
static void Main(string[] args)
{
var a = StringBuilder.ChangeFirstLetterCase("vishnu");
Console.WriteLine(a);
Console.ReadLine();
}
}
Since the return type of this method ChangeFirstLetterCase() is a string. So I'm just doing the conversion like below
`return charArray.ToString();`
So in the method call it is returning the System.Char[]
Alternatively I tried the below one as well
`return new string(charArray);`
So this is returning the value as expected
Argument to the method - "vishnu"
Return value - "Vishnu"
So my question here is
Since the return type of the method is string, what's wrong with below conversion?
return charArray.ToString();
How do we know when to return as new string?.
return new string(charArray);
Please provide me some example
If you return the char array as a String, it will return you the name of the object System.Char[]. This is because the ToString method of char arrays does not build the characters of the array into a usable string, but simply makes a String that states the type of object.
However, if you use new String(char[]), this will read the contents of the char array to build a string out of whatever characters are in the char array. So, you will want to use new String(char[]) for most of your String building, I cannot think of any real uses for using the ToString() on a char array.
So, for your example, you should use return new String(charArray); instead of return charArray.ToString();.
charArray.ToString(); returns the type name because it's implemented that way, for getting string back from a character array you will always have to use String class constructor.
ToString method for char[] is not implemented in a way to return the character array back as a string literal, so use String constructor as you did in the second case.
You could return:
if(inputData[0].IsLower())
return string.Concat(inputData[0].ToUpper(), inputData.Substring(1));
else
return string.Concat(inputData[0].ToLower(), inputData.Substring(1));
Your value would already be a usable string and wouldn't need to have a char[].
I'm not really sure what you gain from converting the string to a char array to being with.

How to create my own parameter method

I saw some code from a C# Console Application that can pass a string-valued parameter . My question is how can I create my own parametered method?
For example, the following code will pass the parameter value to {0} and print the string with value of Leonel.
Console.Write("{0}", "Leonel");
How can I make a method that can pass a parameter value to string format and return a parameterize string?
public string Combine(string format, params object[] args)
{
var parameterize = //("{0}", args) //I need something like this.
return parameterize;
}
I'm not totally clear on what you're asking, but would calling string.Format work?
string str = string.Format("The value is: {0}", val);
That should call the same underlying function as Console.Write does. It returns the string that would otherwise be printed to the Console. Given that, you probably don't even want your Combine method, as string.Format would take its place.
You can use the static method
string.Format(string str, params string[] formatters);
with your example:
public string Combine(string format, params object[] args)
{
var parameterize = string.Format(format, args);
return parameterize;
}

Ranorex Passing Array as Parameter

I have some calculations to complete. I want to send my array to a method that does some calculations. How do I format the sending method here? How do I format the receiving signature line of the receipient method? How do I split the array to use each element?
public void PercentCompare()
{
string[] cells = {
"Repo.Path.ToString()",
"Repo.Path.ToString()",
"Repo.Path.ToString()"
};
Path.CountDoublePercent(cells[]);
}
public static void CountD(string[] cells)
{
//trims
string trimRow1 = string.Empty;
string trimRow2 = string.Empty;
string trimTotal = string.Empty;
}
http://www.ranorex.com/forum/passing-array-as-usercode-argument-t8098.html
this site says: it’s not possible to use an array as an argument for UserCode methods
Can you really do it with no errors?

Parsing formatted string

I am trying to create a generic formatter/parser combination.
Example scenario:
I have a string for string.Format(), e.g. var format = "{0}-{1}"
I have an array of object (string) for the input, e.g. var arr = new[] { "asdf", "qwer" }
I am formatting the array using the format string, e.g. var res = string.Format(format, arr)
What I am trying to do is to revert back the formatted string back into the array of object (string). Something like (pseudo code):
var arr2 = string.Unformat(format, res)
// when: res = "asdf-qwer"
// arr2 should be equal to arr
Anyone have experience doing something like this? I'm thinking about using regular expressions (modify the original format string, and then pass it to Regex.Matches to get the array) and run it for each placeholder in the format string. Is this feasible or is there any other more efficient solution?
While the comments about lost information are valid, sometimes you just want to get the string values of of a string with known formatting.
One method is this blog post written by a friend of mine. He implemented an extension method called string[] ParseExact(), akin to DateTime.ParseExact(). Data is returned as an array of strings, but if you can live with that, it is terribly handy.
public static class StringExtensions
{
public static string[] ParseExact(
this string data,
string format)
{
return ParseExact(data, format, false);
}
public static string[] ParseExact(
this string data,
string format,
bool ignoreCase)
{
string[] values;
if (TryParseExact(data, format, out values, ignoreCase))
return values;
else
throw new ArgumentException("Format not compatible with value.");
}
public static bool TryExtract(
this string data,
string format,
out string[] values)
{
return TryParseExact(data, format, out values, false);
}
public static bool TryParseExact(
this string data,
string format,
out string[] values,
bool ignoreCase)
{
int tokenCount = 0;
format = Regex.Escape(format).Replace("\\{", "{");
for (tokenCount = 0; ; tokenCount++)
{
string token = string.Format("{{{0}}}", tokenCount);
if (!format.Contains(token)) break;
format = format.Replace(token,
string.Format("(?'group{0}'.*)", tokenCount));
}
RegexOptions options =
ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None;
Match match = new Regex(format, options).Match(data);
if (tokenCount != (match.Groups.Count - 1))
{
values = new string[] { };
return false;
}
else
{
values = new string[tokenCount];
for (int index = 0; index < tokenCount; index++)
values[index] =
match.Groups[string.Format("group{0}", index)].Value;
return true;
}
}
}
You can't unformat because information is lost. String.Format is a "destructive" algorithm, which means you can't (always) go back.
Create a new class inheriting from string, where you add a member that keeps track of the "{0}-{1}" and the { "asdf", "qwer" }, override ToString(), and modify a little your code.
If it becomes too tricky, just create the same class, but not inheriting from string and modify a little more your code.
IMO, that's the best way to do this.
It's simply not possible in the generic case. Some information will be "lost" (string boundaries) in the Format method. Assume:
String.Format("{0}-{1}", "hello-world", "stack-overflow");
How would you "Unformat" it?
Assuming "-" is not in the original strings, can you not just use Split?
var arr2 = formattedString.Split('-');
Note that this only applies to the presented example with an assumption. Any reverse algorithm is dependent on the kind of formatting employed; an inverse operation may not even be possible, as noted by the other answers.
A simple solution might be to
replace all format tokens with (.*)
escape all other special charaters in format
make the regex match non-greedy
This would resolve the ambiguities to the shortest possible match.
(I'm not good at RegEx, so please correct me, folks :))
After formatting, you can put the resulting string and the array of objects into a dictionary with the string as key:
Dictionary<string,string []> unFormatLookup = new Dictionary<string,string []>
...
var arr = new string [] {"asdf", "qwer" };
var res = string.Format(format, arr);
unFormatLookup.Add(res,arr);
and in Unformat method, you can simply pass a string and look up that string and return the array used:
string [] Unformat(string res)
{
string [] arr;
unFormatLoopup.TryGetValue(res,out arr); //you can also check the return value of TryGetValue and throw an exception if the input string is not in.
return arr;
}

Categories