Mocking a protected method always returning true - c#

I have the following protected method in my base class:
protected bool ExecuteInteraction(string identifier,
Action<object> interactionFinished, params object[] args)
{
Contract.Requires(!string.IsNullOrEmpty(identifier));
Contract.Requires(interactionFinished != null);
bool result = false;
if (!string.IsNullOrEmpty(identifier) && (interactionFinished != null))
{
// Find the matching interaction behavior.
IInteractionBehavior interactionBehavior =
InteractionBehaviorCollection.Instance.Get(identifier);
if (interactionBehavior != null)
{
try
{
interactionBehavior.Execute(interactionFinished, args);
result = true;
}
catch (Exception)
{
}
}
else
{
Debug.WriteLine(string.Format(
"InteractionBehavior with identifier [{0}] is unknown",
identifier));
}
}
return result;
}
It's basically from this article: http://www.codeproject.com/Articles/708346/Dialogs-the-MVVM-Way ...
This method is used in my derived class like that:
protected override void Delete()
{
try
{
if (PrimaryModel.Id != 0 && PrimaryModel.AddressId != 0)
{
ExecuteInteraction("DeleteConfirmation", (result) =>
{
MessageBoxResult messageBoxResult = (MessageBoxResult)result;
if (messageBoxResult == MessageBoxResult.Yes)
{
//Do something ...
}
});
}
}
catch (Exception exc)
{
Message = exc.Message;
}
}
This doesn't work in my unit test because I don't simulate that messageBoxResult is MessageBoxResult.Yes. This is the reason why I'd like my protected method to always returning true in the unit test. How can I do that (with moq)?

You just need to interface your MessageBox actions so that you can provide a MockMessageBox when unit testing that always returns MessageBoxResult.Yes. So, in your code, don't reference any MessageBoxes directly. Create a WindowManager or MessageBoxService class that you call instead, kind of like a proxy message box.
For example, try something like this:
public string ShowMessageBox(string message, string title, string buttons, string icon)
{
MessageBoxButton messageBoxButtons;
switch (buttons.ToLower())
{
case "ok": messageBoxButtons = MessageBoxButton.OK; break;
case "okcancel": messageBoxButtons = MessageBoxButton.OKCancel; break;
case "yesno": messageBoxButtons = MessageBoxButton.YesNo; break;
case "yesnocancel": messageBoxButtons = MessageBoxButton.YesNoCancel; break;
default: messageBoxButtons = MessageBoxButton.OKCancel; break;
}
MessageBoxImage messageBoxImage;
switch (icon.ToLower())
{
case "asterisk": messageBoxImage = MessageBoxImage.Asterisk; break;
case "error": messageBoxImage = MessageBoxImage.Error; break;
case "exclamation": messageBoxImage = MessageBoxImage.Exclamation; break;
case "hand": messageBoxImage = MessageBoxImage.Hand; break;
case "information": messageBoxImage = MessageBoxImage.Information; break;
case "none": messageBoxImage = MessageBoxImage.None; break;
case "question": messageBoxImage = MessageBoxImage.Question; break;
case "stop": messageBoxImage = MessageBoxImage.Stop; break;
case "warning": messageBoxImage = MessageBoxImage.Warning; break;
default: messageBoxImage = MessageBoxImage.Stop; break;
}
return MessageBox.Show(message, title, messageBoxButtons, messageBoxImage).ToString();
}
This would be called like this:
string result = WindowManager.ShowMessageBox(message, title, "OkCancel", "Question");
Note how there are no direct relations to any UI dlls... all properties are string based. Now you need to interface the class that this method is in (WindowManager). So now we have an IWindowManager that forces us to write a ShowMessageBox method in all implementing classes.
Now we implement this interface in a MockWindowManager class:
public string ShowMessageBox(string message, string title, string buttons, string icon)
{
switch (buttons)
{
case "Ok":
case "OkCancel": return "OK";
case "YesNo":
case "YesNoCancel": return "Yes";
default: return "OK";
}
}
When running the application, we use the WindowManager class and when testing, we use the MockWindowManager class. This can be achieved in a number of ways, but the easiest is to pass an IWindowManager into the view model constructor:
public YourViewModel(IWindowManager windowManager)
{
this.windowManager = windowManager;
}

I really suggest you to follow the concept explained by #Sheridan; but if you want to go your way, here is the solution how to mock a protected method:
Mock<YourBaseClass> baseClassMock = new Mock<YourBaseClass>();
baseClassMock.Protected().Setup<bool>(
"ExecuteInteraction",
ItExpr.IsAny<string>(),
ItExpr.IsAny<Action<object>>(),
ItExpr.IsAny<object[]>())
.Returns(true);

Related

C# PropertyGrid UITypeEditor Agnostic to the object and property

In the last couple of weeks I've been learning PropertyGrid. I need to display the properties of a series of objects of various classes, but they are all derived from class Ctrl. For instance, there are:
Ctrl_BUTTON
Ctrl_SQLLISTVIEW
Ctrl_TEXTBOX
nine classes in all
The derived classes contain the additional properties that are not in the base class and only apply to some of the derived classes. Each property can either be of a specific type of an Expression (a class that allows the user to enter a string that will later evaluate to a canonical value). In the PropertyGrid, I've implemented a dropdown by writing class ExpressionPropertyEditor which inherits UITypeEditor. I've currently only implemented the Ctrl_TEXTBOX.ReadOnly property which can be a bool, or an Expression, and it provides a dropdown that looks like this before the user has entered an expression:
or something like this if they have:
When the user clicks on the Expression entry, an expression editor is opened. Currently the relevant parts of my Ctrl_TEXTBOX class look like this:
public class Ctrl_TEXTBOX : Ctrl
{
private object _readOnly = false;
[DescriptionAttribute("Whether the user can change the contents.")]
[Editor(typeof(ExpressionPropertyEditor), typeof(UITypeEditor))]
public object ReadOnly
{
get
{
return _readOnly;
}
set
{
try
{
_readOnly = ExpressionHelper.BoolExp2Object(value);
}
catch (Exception ex)
{
base.Globals.Errs.Raise(ex);
throw ex;
}
}
}
}
For reference ExpressionHelper contains this, simply:
public static class ExpressionHelper
{
public static object BoolExp2Object(object oValue)
{
try
{
switch (Helper.GetClassNameFromObject(oValue).ToLower())
{
case "expression": return oValue;
case "string":
switch (((string)oValue).ToLower())
{
case "true": return true;
case "false": return false;
default: throw new NotImplementedException();
}
case "boolean":
case "bool": return oValue;
default: throw new NotImplementedException();
}
}
catch (Exception ex)
{
throw ex;
}
}
}
My implementation of ExpressionPropertyEditor looks like this:
public class ExpressionPropertyEditor : UITypeEditor
{
private IWindowsFormsEditorService _editorService;
private ListBox _listBox;
private Ctrl _ctrl;
public ExpressionPropertyEditor()
{
}
// Displays the UI for value selection.
public override object EditValue(ITypeDescriptorContext context, System.IServiceProvider provider, object value)
{
// coded with help from: https://stackoverflow.com/questions/5171037/display-list-of-custom-objects-as-a-drop-down-in-the-propertiesgrid
Ctrl oCtrl;
Ctrl_TEXTBOX oTextBox;
Expression oExp = null;
frmExpressionEditor2 frm;
bool bOk = false;
_editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
_listBox = new ListBox();
_listBox.SelectionMode = SelectionMode.One;
_listBox.SelectedValueChanged += EventHandler_ListBox_SelectedValueChanged;
_listBox.Items.Add(true);
_listBox.Items.Add(false);
switch (Helper.GetClassNameFromObject(context.Instance))
{
case "Ctrl_TEXTBOX":
oTextBox = (Ctrl_TEXTBOX)context.Instance;
switch (Helper.GetClassNameFromObject(oTextBox.ReadOnly))
{
case "Boolean":
case "bool":
// cos we need a way to make an expression
oExp = new Expression(oTextBox.Globals, "BOOLEAN", enumExpressionSource.Expression, Consts.EXPRESSION_PROPERTY_NAME);
_listBox.Items.Add(oExp);
break;
case "Expression":
oExp = (Expression)oTextBox.ReadOnly;
_listBox.Items.Add(oExp);
break;
default:
// this shouldn't happen really; just wrap as an expression
oExp = new Expression(oTextBox.Globals, "BOOLEAN", enumExpressionSource.Expression, Consts.EXPRESSION_PROPERTY_NAME);
_listBox.Items.Add(oExp);
break;
}
break;
}
_ctrl = (Ctrl)context.Instance;
_editorService.DropDownControl(_listBox); // this will return when EventHandler_ListBox_SelectedValueChanged calls editorService.CloseDropDown, like a modal dialog.
if (_listBox.SelectedItem == null) // no selection, return the passed-in value as is
return value;
if (Helper.GetClassNameFromObject(_listBox.SelectedItem) == "Expression")
{
frm = new frmExpressionEditor2();
if (!frm.EditExpression(_ctrl.Globals, _ctrl.Server, _ctrl.App, _ctrl.Frm, ref oExp, ref bOk)) throw new Exception("Could not open expression editor.");
}
return _listBox.SelectedItem;
}
private void EventHandler_ListBox_SelectedValueChanged(object sender, EventArgs e)
{
_editorService.CloseDropDown();
}
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
}
public override bool IsDropDownResizable
{
get { return true; }
}
}
My question is: how do I generalize ExpressionPropertyEditor so that I can use it on any of the derived classes of Ctrl, for any of the boolean properties that I want to include Expressions with? Currently it is locked to Ctrl_TEXTBOX.ReadOnly. If this is not possible to do, I have to created dozens of classes containing identical logic with just the names changed - not good for code reuse.
Thanks to #Rubidium 37's comments above, I've modified EditValue method so that it doesn't need to bind tightly to a sub-class of Ctrl and can use any property name. I've then used the PropertyInfo class in System.Reflection to obtain the current value of the property without having to hardcode the property name.
Just the updated EditValue method is posted.
public override object EditValue(ITypeDescriptorContext context, System.IServiceProvider provider, object value)
{
// coded with help from: https://stackoverflow.com/questions/5171037/display-list-of-custom-objects-as-a-drop-down-in-the-propertiesgrid
Ctrl oCtrl = null;
Expression oExp = null;
frmExpressionEditor2 frm = null;
bool bOk = false;
System.Reflection.PropertyInfo oPropInfo = null;
string cPropertyName = "";
object oCurrentValue = null;
try
{
oCtrl = (Ctrl)context.Instance;
_editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
// setup a listbox with the possible values the boolean can take, true, false, and an expression
_listBox = new ListBox();
_listBox.SelectionMode = SelectionMode.One;
_listBox.SelectedValueChanged += EventHandler_ListBox_SelectedValueChanged;
//_listBox.DrawItem += EventHandler_ListBox_DrawItem; // do this if you have loads of time and want a pretty fx next to the Expression
_listBox.Items.Add(true);
_listBox.Items.Add(false);
// we either want to show Consts.EXPRESSION_PROPERTY_NAME, or if the value of the property is currently an expression, show that instead
cPropertyName = context.PropertyDescriptor.Name;
oPropInfo = context.Instance.GetType().GetProperty(cPropertyName);
oCurrentValue = oPropInfo.GetValue(context.Instance, null); // this returns the current value of the property
switch (Helper.GetClassNameFromObject(oCurrentValue))
{
case "Boolean":
case "bool": // just show the default expression string
oExp = new Expression(oCtrl.Globals, "BOOLEAN", enumExpressionSource.Expression, Consts.EXPRESSION_PROPERTY_NAME);
_listBox.Items.Add(oExp);
break;
case "Expression": // show the current value of the boolean expression
oExp = (Expression)oCurrentValue;
_listBox.Items.Add(oExp);
break;
default: // this shouldn't happen, so reset to default expression string
oExp = new Expression(oCtrl.Globals, "BOOLEAN", enumExpressionSource.Expression, Consts.EXPRESSION_PROPERTY_NAME);
_listBox.Items.Add(oExp);
break;
}
// show the list
_editorService.DropDownControl(_listBox); // this will return when EventHandler_ListBox_SelectedValueChanged calls editorService.CloseDropDown, like a modal dialog.
// no selection, return the passed-in value as is
if (_listBox.SelectedItem == null) return value;
// and if necessary, allow the user to edit the expression
if (Helper.GetClassNameFromObject(_listBox.SelectedItem) == "Expression")
{
frm = new frmExpressionEditor2();
if (!frm.EditExpression(oCtrl.Globals, oCtrl.Server, oCtrl.App, oCtrl.Frm, ref oExp, ref bOk)) throw new Exception("Could not open expression editor.");
return oExp;
}
return _listBox.SelectedItem;
}
catch (Exception ex)
{
oCtrl.Globals.Errs.Raise(ex);
return null;
}
}

Function parameters - how to use a pre-defined list instead of string value

This should be simple but I can't seem to figure it out. I have a function to send data to an API:
public bool UpdateCustomer(int customerid, string status)
{
apicall(customerid, status);
return true;
}
UpdateCustomer(1234, "shipped")
This works fine. But the API has a predefined list of acceptable statuses, and I don't want to leave it to the person calling the function to get it right, I want to create some sort of enum or something:
public bool UpdateCustomer(int customerid, Status status)
{
apicall(customerid, status);
return true;
}
UpdateCustomer(1234, Statuses.Shipped)
I want to pass the value to the API of their actual accepted value, "shipped".
I've tried creating a class with static strings:
public class Status
{
public static string Cancelled = "cancelled";
public static string Unsubmitted = "unsubmitted";
public static string Saved = "saved";
public static string Submitted = "submitted";
public static string Arrived = "arrived";
public static string Completed = "completed";
public static string Shipped = "shipped";
}
but when I go to call UpdateCustomer(1234, Status.Shipped), it says it can't convert from a string to Status. I've done this with enums plenty of times but I can't use an enum because those only support int values.
What is the easiest way of doing this with string values (or anything besides integers, really)?
Edit: It does work if I set the function to public bool UpdateCustomer(int customerid, string status) and call it with UpdateCustomer(1234, Statuses.Shipped) but that defeats the purpose of idiot-proofing this, you can still pass whatever string value you want. I really want the function parameter to be type of Status so it forces the caller to use one of the pre-defined statuses.
enum Status
{
Cancelled,
Saved,
..
}
public bool UpdateCustomer(int customerid, Status status)
{
apicall(customerid, status.ToString());
return true;
}
enum StatusEnum
{
Cancelled,
Unsubmitted,
Saved,
Submitted,
Arrived,
Completed,
Shipped
}
public bool UpdateCustomer(int customerid, StatusEnum status)
{
string statusStr;
switch(status)
{
case StatusEnum.Cancelled:
statusStr = "cancelled";
break;
case StatusEnum.Unsubmitted:
statusStr = "unsubmitted";
break;
case StatusEnum.Saved:
statusStr = "saved";
break;
case StatusEnum.Submitted:
statusStr = "submitted";
break;
case StatusEnum.Arrived:
statusStr = "arrived";
break;
case StatusEnum.Completed:
statusStr = "completed";
break;
case StatusEnum.Shipped:
statusStr = "shipped";
break;
case default:
throw new NotImplementedException();
}
apicall(customerid, statusStr);
return true;
}
This can be done with a dictionary. Let's say you have a "Status" enum with 3 values. Complete, Incomplete, and Abandoned. Then you'll want to create a dictionary to be used as a lookup table.
Dictionary<Status, string> statusDict = new Dictionary<Status, string>()
{
{ Status.Complete, "Complete" },
{ Status.Incomplete, "Incomplete" },
{ Status.Abandoned, "Abandoned" }
};
When you receive the Status enum from them (CustomerStatus), all you need to do for your API call is...
apicall(customerID, statusDict[CustomerStatus]);

Get Array values using a class in c#

i have declared 2 string values eg: ChName1, ChName2 and 2 int values eg: Delay1, Delay2 in the settings.
i would like to implement an array in class so life will be more easier. can somebody correct my code with necessary explanations
public class GetDefaultValues
{
public string Name[int i]
{
get
{
switch (i)
{
case 0:
return Name.Properties.Settings.Default.ChName1;
case 1:
return Name.Properties.Settings.Default.ChName2;
default:
return "Not Implemented";
}
}
set
{
switch (i)
{
case 0:
{
Name.Properties.Settings.Default.ChName1 = value;
break;
}
case 1:
{
Name.Properties.Settings.Default.ChName2 = value;
break;
}
}
Name.Properties.Settings.Default.Save();
}
}
public int Value[int i]
{
get
{
switch (i)
{
case 0:
return Name.Properties.Settings.Default.Delay1;
case 1:
return Name.Properties.Settings.Default.Delay2;
default:
return 0;
}
}
set
{
switch (i)
{
case 0:
{
Name.Properties.Settings.Default.Delay1 = value;
break;
}
case 1:
{
Name.Properties.Settings.Default.Delay2 = value;
break;
}
}
Name.Properties.Settings.Default.Save();
}
}
}
then in my main code i could do like this
GetDefaultValues Vlues = new GetDefaultValues();
Vlues.Name[0] = "SomeName";
string SomeString = Vlues.Name[1];
Vlues.Value[0] = 125;
int SomeInt = Vlues.Value[1];
this code is generating errors in my code.
Error 2 Bad array declarator: To declare a managed array the rank
specifier precedes the variable's identifier. To declare a fixed size
buffer field, use the fixed keyword before the field type
will be happy if i could know why??
please help!!
I would recommend not to use properties for this because properties should not have that logic. You should use methods instead.
This could be look like this for example (just added the name as a sample).
public class GetDefaultValues
{
public bool SetName(int i, string value)
{
switch (i)
{
case 0:
{
Name.Properties.Settings.Default.ChName1 = value;
break;
}
case 1:
{
Name.Properties.Settings.Default.ChName2 = value;
break;
}
default:
return false;
}
Name.Properties.Settings.Default.Save();
return true;
}
public string GetName(int i)
{
switch (i)
{
case 0:
return Name.Properties.Settings.Default.ChName1;
case 1:
return Name.Properties.Settings.Default.ChName2;
default:
return "Not Implemented";
}
}
}
This would be called like this
GetDefaultValues Vlues = new GetDefaultValues();
bool success = Vlues.SetName(0, "SomeName");
string SomeString = Vlues.Name(1);
You can make the SetName method a void method if you don't want to have the info if it worked or not.

Unit testing void methods in C#?

Trying to test a void method that sends an email whenever one action occurred. Most of the parameter in this method inside is hard coded. Based on the switch case mail subject also changes.
public void SendMail(ControllerContext, admin, userList)
{
try
{
var templatePath = string.Empty;
switch (pathid)
{
case 1:
templatePath = "XXX";
default:
break;
}
switch (urlId)
{
case 1:
viewModel.ItemUrl = "URL";
break;
default:
break;
}
foreach (var user in userList)
{
viewModel.FirstName = user.FirstName;
viewModel.LastName = user.LastName;
string bodyOftheContent = Generator.TemplateGeneration(ControllerContext, tempatePath);
Object.SendCustomMail(user.Email, bodyOftheContent, subject);
}
}
catch (Exception ex)
{
LogError("Error in sending notification email", ex, MethodBase.GetCurrentMethod());
}
}
Any possible way to unit test void method inside has lots of hard-coded values
You cannot unit test a void method, but you can make a void method part of a unit test to see if a desired mutation has occured in a class property, supplied input document or record in the database.
I.e.
public class SimpleEmailTest
{
private int _sentEmails;
public SimpleEmailTest()
{
this._sentEmails = 0;
}
[TestMethod]
public void TestIfEmailsGetSent()
{
SendEmail();
Assert.IsTrue(_sentEmails == 1);
}
public void SendEmail
{
// do email sending
_sentEmails++;
}
}

Classes with String Switches

class AddItemOption
{
//Fields that contain class data
string input = Console.ReadLine();
//Methods that define class functionality
public string myFunction(string Value)
{
switch (input)
{
case "Umbrella":
Console.WriteLine("Umbrella is selected");
break;
case "Rain Coat":
Console.WriteLine("Raincoat is selected");
break;
case "Boots":
Console.WriteLine("Boots is selected");
break;
case "Hood":
Console.WriteLine("Hood is selected");
break;
default:
Console.WriteLine("Input not reconized, please choose another item");
break;
}
}
I get the error "Not all code paths return a value". It is from myFunction(string Value). I'm not sure how to return this, or what to put in the parameter to get it to work. Do I need something below it too? I am new to classes. Please tell me if I'm doing this all wrong or if that is where the switch statement should go!
public AddItemOption(string input)
{
}
FROM Shyju I changed it to:
class AddItemOptionOne
{
//Fields that contain class data
string input = Console.ReadLine();
//Methods that define class functionality
public string myFunction(string Value)
{
switch (input)
{
case "Key Chain":
return "Key Chain is selected";
break;
case "Leather Armor":
return "Leather Armor is selected";
break;
case "Boots":
return "Boots is selected";
break;
case "Sword":
return "Sword is selected";
break;
default:
return "Input not reconized, please choose another item";
break;
}
}
However, it does not recognize the breaks. "Unreachable Code Detected"
Your method has a return type of string. That means your method should always return some string. But you are not returning a string. instead you are Writing it to the console using WriteLine method.
So Change
Console.WriteLine("Umbrella is selected");
to
return "Umbrella is selected";
OR
You can change your method's return type to void.
public void myFunction(string Value)
{
//your current fancy stuff here
Console.WriteLine("My method dont have a return type");
}
EDIT : AS per the question edit.
return statement will take the control out from your method. that means the next line (break) won't be executed. So remove the break statement.
case "Key Chain":
return "Key Chain is selected";
Well... You don't return anything from your function, so change it to
public void myFunction(string Value)
Try this:
class AddItemOptionOne
{
//Methods that define class functionality
public string myFunction(string input)
{
string result = string.Empty;
switch (input)
{
case "Key Chain":
result = "Key Chain is selected";
break;
case "Leather Armor":
result = "Leather Armor is selected";
break;
case "Boots":
result = "Boots is selected";
break;
case "Sword":
result = "Sword is selected";
break;
default:
result = "Input not reconized, please choose another item";
break;
}
return result;
}
}

Categories