Hello I'm trying to test a class that represents layout theme of GUI. It has color and size properties and a method that sets the default values.
public class LayoutTheme : ILayoutTheme
{
public LayoutTheme()
{
SetTheme();
}
public void SetTheme()
{
WorkspaceGap = 4;
SplitBarWidth = 4;
ApplicationBack = ColorTranslator.FromHtml("#EFEFF2");
SplitBarBack = ColorTranslator.FromHtml("#CCCEDB");
PanelBack = ColorTranslator.FromHtml("#FFFFFF ");
PanelFore = ColorTranslator.FromHtml("#1E1E1E ");
// ...
}
public int WorkspaceGap { get; set; }
public int SplitBarWidth{ get; set; }
public Color ApplicationBack { get; set; }
public Color SplitBarBack { get; set; }
public Color PanelBack { get; set; }
public Color PanelFore { get; set; }
// ...
}
I need to test:
1. If all of the properties are set by the SetTheme method.
2. If there is no duplication in setting a property.
For the first test, I first cycle through all properties and set an unusual value. After that I call SetTheme method and cycle again to check if all properties are changed.
[Test]
public void LayoutTheme_IfPropertiesSet()
{
var theme = new LayoutTheme();
Type typeTheme = theme.GetType();
PropertyInfo[] propInfoList = typeTheme.GetProperties();
int intValue = int.MinValue;
Color colorValue = Color.Pink;
// Set unusual value
foreach (PropertyInfo propInfo in propInfoList)
{
if (propInfo.PropertyType == typeof(int))
propInfo.SetValue(theme, intValue, null);
else if (propInfo.PropertyType == typeof(Color))
propInfo.SetValue(theme, colorValue, null);
else
Assert.Fail("Property '{0}' of type '{1}' is not tested!", propInfo.Name, propInfo.PropertyType);
}
theme.SetTheme();
// Check if value changed
foreach (PropertyInfo propInfo in propInfoList)
{
if (propInfo.PropertyType == typeof(int))
Assert.AreNotEqual(propInfo.GetValue(theme, null), intValue, string.Format("Property '{0}' is not set!", propInfo.Name));
else if (propInfo.PropertyType == typeof(Color))
Assert.AreNotEqual(propInfo.GetValue(theme, null), colorValue, string.Format("Property '{0}' is not set!", propInfo.Name));
}
}
Actually the test works well and I even found two missed settings, but I don't think it is written well.
Probably it can be don with Moq of the interface and check if all properties are set.
About the second test, don't have idea how to do it. Probably mocking and checking the number of calls can do it. Any help?
Thank you!
For testing if all properties are set to certain values, I would implement Equals() for this class and create a second object with known values and check for equality. This also comes in handy when testing for state changes etc.
I would certainly not test if a property gets set multiply times if there is no explicit reason to do it.
Related
Say we work with this class:
public class UsefulClass
{
public string A { get; set; }
public string B { get; set; }
public int? C { get; set; }
public int? D { get; set; }
public decimal E { get; set; }
public decimal F { get; set; }
}
Let's consider the following instance:
UsefulClass z_objUsefulInstance = new UsefulClass()
{
A = null,
C = null,
E = 0
};
At this point, z_objUsefulInstance.A and C are null, E is 0, B, D and F have not been initialized.
Is there a way to tell, automatically, which properties of z_objUsefulInstance haven't been initialized and which ones have been initialized with null or 0?
EDIT: by popular demand, why I need this: to emulate a system of database access akin to EntityFramework. Right now all properties are a specific generic type, so it's rather easy to know which is null and which is Generic<T>.HasNullValue == true. But that generic type causes various issues and now we'd like to get rid of it, particularly as we have grown more conversant with Expressions.
Is there a way to tell, automatically, which properties of z_objUsefulInstance haven't been initialized and which ones have been initialized with null or 0?
You can't really know in ways that you can easily inspect at runtime what properties have been set unless you intercept the property setter and set some sort of flag. from a first-principals perspective that would resemble something like this:
public class UsefulClass
{
public string A { get => _a; set { _a = value; A_Set = true; } }
private string _a;
private bool A_Set = false;
public string B { get => _b; set { _b = value; B_Set = true; } }
private string _b;
private bool B_Set = false;
public int? C { get => _c; set { _c = value; C_Set = true; } }
private string _c;
private bool C_Set = false;
public int? D { get => _d; set { _d = value; D_Set = true; } }
private string _d;
private bool D_Set = false;
public decimal E { get => _e; set { _e = value; E_Set = true; } }
private string _e;
private bool E_Set = false;
public decimal F { get => _f; set { _f = value; F_Set = true; } }
private string _f;
private bool F_Set = false;
}
It is pretty verbose, but you can see here how we are not comparing the value at all, we can determine definitively if each property has been set, thought not specifically during the initialization of the instance, this simple code only tracks if each property was set at all.
So after your init, we can inspect these new flags:
UsefulClass z_objUsefulInstance = new UsefulClass()
{
A = null,
C = null,
E = 0
};
Console.WriteLine(z.C_Set); // True
Console.WriteLine(z.D_Set); // False
We can simplify this with a dictionary for the backing store and helper methods to get and set the property values, we can even encapsulate that logic in a base class to make this easier to consume:
public class UsefulClass : PropertyTracker
{
public string A { get => GetProperty<string>(); set => SetProperty(value); }
public string B { get => GetProperty<string>(); set => SetProperty(value); }
public int? C { get => GetProperty<int?>(); set => SetProperty(value); }
public int? D { get => GetProperty<int?>(); set => SetProperty(value); }
public decimal E { get => GetProperty<decimal>(); set => SetProperty(value); }
public decimal F { get => GetProperty<decimal>(); set => SetProperty(value); }
}
public abstract class PropertyTracker
{
private Dictionary<string, object> _values = new Dictionary<string, object>();
protected void SetProperty<T>(T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
{
_values[propertyName] = value;
}
protected T GetProperty<T>([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
{
if (!_values.ContainsKey(propertyName))
return default;
return (T)_values[propertyName];
}
public bool IsSet(string propertyName)
{
return _values.ContainsKey(propertyName);
}
}
See we still have the concept of a backing store, it's just not a field anymore. The inspection code is a bit different too:
UsefulClass z_objUsefulInstance = new UsefulClass()
{
A = null,
C = null,
E = 0
};
Console.WriteLine(z.IsSet(nameof(UsefulClass.C)); // True
Console.WriteLine(z.IsSet(nameof(UsefulClass.D)); // False
There are all sorts of techniques you can use to scaffold this or similar code out across your classes, this is just an example implementation. You could even write a generic wrapper that uses reflection to do the same thing. In my solutions I tend to use T4 templates to generate what are effectively View Model classes. My main argument was that I could generate some verbose code and take a hit at compile-time instead of a performance hit at runtime with a reflection based implementation.
If your ViewModel classes inherit from your model class, then you can get close to an apparently automatic implementation that is more compatible with the rest of your runtime, but that would require your properties be declared as virtual to enable the inheriting class to override the implementation.
If you end up going down this route, consider adding value to your classes by implementing INotifyPropertyChanged, or perhaps IChangeTracking or IRevertibleChangeTracking while you're there.
UsefulClass z_objUsefulInstance = new UsefulClass() {
A = null
C = null,
E = 0
};
At this point, z_objUsefulInstance.A and C are null, E is 0,
B, D and F have not been initialized.
No that's not quite right.
From "14.11.4 Constructor Execution" in the C#7 language spec
Variable initializers are transformed into assignment statements, and these assignment statements are executed before the invocation of the base class instance constructor.
So before your instance constructor in the above example is started executing, the properties are assigned
A = default(string); // null
B = default(string); // null
C = default(int?); // null
D = default(int?); // null
E = default(decimal); // 0.0m
F = default(decimal); // 0.0m
(Not quite accurate, but close enough for this answer)
Then your instance constructor is run (in this example, the default provided by the compiler), then your property assignments are made
A = null,
C = null,
E = 0
. There's no difference between E = 0 and E = default(decimal), nor is there a difference between null and null (default(string)).
If you need to tell whether a property was set or not you will have to provide a backing field, or otherwise control access to the property.
If you want to read more about constructor details, a friendlier summary than the language spec can be found at https://jonskeet.uk/csharp/constructors.html .
I may not have a good grasp of the ?? operator yet and ran into a design flaw I couldn't explain.
Compare the following two properties, the only difference being how there are initialized: the first explicitly initialized, while the second with the ?? operator (or am I doing it wrong here?).
If I run data init with both properties, the collection based on the first property comes up populated as expected, while the second one with the ?? operator never gets populated and comes up with 0 elements in the collection.
Surely something is wrong here in my assumption; what is the flaw here?
P.S. Please ignore the Set method which is to implement INotifyPropertyChanged in the base class and has no bearing on this issue (which is confined to the type of initialization).
// property version 1
private ObservableCollection<UserName> _userNameColl = new ObservableCollection<UserName>();
public ObservableCollection<UserName> UserNameColl
{
get { return _userNameColl; }
set { Set(ref _userNameColl, value); }
}
// property version 2
private ObservableCollection<UserName> _userNameColl;
public ObservableCollection<UserName> UserNameColl
{
get { return _userNameColl ?? new ObservableCollection<UserName>(); }
set { Set(ref _userNameColl, value); }
}
// a simple class for creating object collection
public class UserName
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
// a simple test populating the collection
for (int i = 0; i < 4; i++)
{
// silly data init just for test
UserNameColl.Add(new UserName()
{
Name = $"UserName No {i}",
Age = 20 + i,
Email = $"email{i}#local.lan"
});
}
The second one never initializes your field but always returns a new collection. Try this one instead:
public ObservableCollection<UserName> UserNameColl
{
get { return _userNameColl ?? (_userNameColl = new ObservableCollection<UserName>()); }
set { Set(ref _userNameColl, value); }
}
I have List of class as :-
public class Requirement
{
public string Id { get; set; }
public string desc { get; set; }
}
List lstRequirement
I have 3 records in this list for Id and desc.
I wanted to check if any of item is not remaining null.
For that I used below :-
bool IsHavingValidTags = lstRequirement.All(_=> _.Id!=null && _.desc!=null);
This condition is working fine with above Linq.
But I wanted to make it as Generic.
Eg. In future there may get added 5 more properties in Requirement class.
After addition of properties I also have to make changes in Linq.
How can I make this Linq condition generic for all properties?
I want to check any of the property is not remaining null in List.
Please help..!!!
I tried With =>
bool IsHavingValidTags = lstRequirement.All(_ => _ != null);
But not giving desired result.
EDIT 1 :
You can write an extension method that uses reflection like the following:
public static class Extensions
{
public static bool AreAllPropertiesNotNullForAllItems<T>(this IEnumerable<T> items)
{
var properties = typeof(T).GetProperties();
return items.All(x => properties.All(p => p.GetValue(x) != null));
}
}
then use like this:
bool IsHavingValidTags = lstRequirement.AreAllPropertiesNotNullForAllItems();
EDIT:
PropertyInfo.GetValue(object obj) method overload was introduced in .NET Framework 4.5. If you are using .NET Framework 4.0 you need to call p.GetValue(x, null)
Instead of this you should make those field not null. this will never allow those field inserted null. keep validations. like bellow.
[Required(ErrorMessage = "First name is required")]
public string first_name { get; set; }
[Required(ErrorMessage = "Last name is required")]
public string last_name { get; set; }
You can use foreach loop to loop through all the object in the list. Then use reflection to get all the properties in each item in the list, then you can loop through those properties to perform your null check.
Foreach (var x in lstRequirement){
List prop = x.GetType().GetProperties();
Foreach (var y in prop){
If (y == null){
IsHavingValidTag = true;
//Then you can return you method here or throw an Exception
}
}
Hope this helps.
You should add an static method to check the Properties of the Class. I will show you the following example.
Instead of your code :
bool IsHavingValidTags = lstRequirement.All(_ => _ != null);
use the following codes:
bool flg = list.All(m => CheckProperties(m));
public static bool CheckProperties<T>(T source)
{
bool rtnFlg = true;
Type t = typeof(T);
var properties = t.GetProperties();
foreach (var prop in properties)
{
var value = prop.GetValue(source, null);
if (value == null)
{
return false;
}
}
return rtnFlg;
}
Please refer to this code
public class A : B
{
[Display(Name = "Initial Score Code", Order =3)]
public Code { get; set; }
[Display(Name = "Initial Score Code", Order =2)]
public Name{ get; set; }
............
}
I need to get all properties of class through order by orderAttribute of Display. I have tried with this code to do
var prop = typeof(A)
.GetProperties()
.OrderBy(p => ((DisplayAttribute)p.GetCustomAttributes(typeof(DisplayAttribute), true).FirstOrDefault).Order);
but it causes an error
object reference not to set an instance of object
I assumed this issue because of some property not having "Order" property in "DisplayAttribute" .
How to handle this kind of situation? I need to order all the properties even though some property not having the value of order property.
You are missing brackets () on FirstOrDefault operator. Also you should deal with case when default value is returned. I suggest to select Order value before getting first or default value. That will return 0 for all properties which don't have DisplayAttribute:
var prop = typeof(A)
.GetProperties()
.OrderBy(p => p.GetCustomAttributes(typeof(DisplayAttribute), true)
.Cast<DisplayAttribute>()
.Select(a => a.Order)
.FirstOrDefault());
If you want properties without DisplayAttribute to be last, you can provide Int32.MaxValue as default value to be returned:
.Select(a => a.Order)
.DefaultIfEmpty(Int32.MaxValue)
.First()
Try this:
var props = from p in typeof(A).GetProperties()
let orderAttribute = (DisplayAttribute)(p.GetCustomAttributes(typeof(DisplayAttribute), true))
.FirstOrDefault()
where orderAttribute != null
orderby orderAttribute.Order
select p;
Or:
var props = from p in typeof(A).GetProperties()
let orderAttribute = (DisplayAttribute)(p.GetCustomAttributes(typeof(DisplayAttribute), true))
.FirstOrDefault()
orderby orderAttribute == null ? 0 : orderAttribute.Order
select p;
Here is a much more complete answer that allows you to better control the ordering of PropertyInfo instances without DisplayAttribute attributes:
public class A
{
[Display(Name = "Initial Score Code", Order = 3)]
public int Code
{
get;
set;
}
[Display(Name = "Initial Score Code", Order = 2)]
public string Name
{
get;
set;
}
}
public class PropertyInfoComparer : IComparer<PropertyInfo>
{
public int Compare(PropertyInfo x, PropertyInfo y)
{
var attribute1 = (DisplayAttribute)x.GetCustomAttributes(typeof(DisplayAttribute)).FirstOrDefault();
var attribute2 = (DisplayAttribute)y.GetCustomAttributes(typeof(DisplayAttribute)).FirstOrDefault();
// If the first property has no attribute, sort it first
if (attribute1 == null)
{
return -1;
}
// If the second property has no attribute, sort it first
if (attribute2 == null)
{
return 1;
}
// Compare the Order properties of both attributes
return attribute1.Order.CompareTo(attribute2.Order);
}
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class DisplayAttribute : Attribute
{
public string Name
{
get;
set;
}
public int Order
{
get;
set;
}
}
Usage:
// Get all the properties of Foo and order them using PropertyInfoComparer
typeof(Foo).GetProperties().OrderBy(arg => arg, new PropertyInfoComparer());
I like the approach with Comparer. However, when I tried it, my iterator went into a dead loop at first. Later, it started throwing exceptions. Also, I optimized it for the case when first property doesn't contain "Order" descriptor to avoid even checking for a second one. I also moved all comments into the class description:
/// <summary>
/// If the first property has no attribute, sort it first
/// If the second property has no attribute, sort it first
/// Compare the Order properties of both attributes
/// </summary>
public class PropertyInfoComparer : IComparer<PropertyInfo>
{
public int Compare(PropertyInfo x, PropertyInfo y)
{
if (x == y) return 0;
var attrX = (DisplayAttribute)x.GetCustomAttributes(typeof(DisplayAttribute)).FirstOrDefault();
int? orderX = attrX?.GetOrder();
if (orderX == null) return -1;
var attrY = (DisplayAttribute)y.GetCustomAttributes(typeof(DisplayAttribute)).FirstOrDefault();
int? orderY = attrY?.GetOrder();
if (orderY == null) return 1;
return ((int)orderX).CompareTo((int)orderY);
}
}
Unfortunately, classes that have properties without the "Order" descriptor lose their "natural" order. Therefore, I ended up checking for any properties that have the "Order" descriptor first. If at least one of them has that descriptor, then do the sorting.
I have an object called Job and inside of it I have strings, ints, and an enum as public objects. Each job is then placed into a Queue and I iterate through the queue in the process.
What I want to do is that when I Dequeue() each job, I can generically iterate through each job and write the public object names and values to the console.
I figured out how to write the object names to console and I can obviously write the values, but the problem is that I don't know how to get each public string/int/enum from the Job object.
I've looked at
C# object dumper
C#: How to get all public (both get and set) string properties of a type
How to select all the values of an object's property on a list of typed objects in .Net with C#
but don't understand how I would use either of the accepted answers there.
Here's the code to my Job class:
class Job
{
#region Constructor
public Job()
{
}
#endregion
#region Accessors
public int var_job { get; set; }
public jobType var_jobtype { get; set; } //this is an enum
public string var_jobname { get; set; }
public string var_content { get; set; }
public string var_contenticon { get; set; }
#endregion
}
Here's the code that's returning the variable's name: (from https://stackoverflow.com/a/2664690/559988)
GetName(new {Job.var_content}) //how I call it
static string GetName<T>(T item) where T : class
{
return typeof(T).GetProperties()[0].Name;
}
Ideally I'd have an output to console like this:
Queuing Jobs Now
--------------------
var_job = its value
var_jobtype = its value
var_jobname = its value
var_content = its value
var_contenticon = its value
Thoughts?
What I think you're looking for is PropertyInfo.GetValue. Perhaps something like this will help (from memory so hopefully it'll work as is):
public static void DumpProperties(this Object dumpWhat)
{
foreach(PropertyInfo prop in dumpWhat.GetType().GetProperties())
Console.WriteLine("{0} = {1}", prop.Name, prop.GetValue(dumpWhat, BindingFlags.GetProperty, null, null, null).ToString());
}
You can also something similar with your object's fields if you tend to use those instead of properties.
public static void DumpFields(this Object dumpWhat)
{
foreach(FieldInfo fld in dumpWhat.GetType().GetFields())
Console.WriteLine("{0} = {1}", fld.Name, fld.GetValue(dumpWhat, BindingFlags.GetField, null, null, null).ToString());
}
These will dump to the console, but it should be straight forward enough to change them to write to any stream.
Update
If you start getting NullReferenceException's from a property not being set, rather than wrapping it in a try...catch, you should do some proactive checks against the value returned from PropertyInfo.GetValue:
public static void DumpProperties(this Object dumpWhat)
{
foreach(PropertyInfo prop in dumpWhat.GetType().GetProperties())
{
string propVal = prop.GetValue(dumpWhat, BindingFlags.GetProperty, null, null, null) as string;
if (propVal != null)
Console.WriteLine("{0} = {1}", prop.Name, propVal);
}
}
Per the suggestion of Tony Hopkinson, you may add the following method override to your Job class:
public override string ToString()
{
string foo =
string.Format( "var_job = {1}{0}var_jobType = {2}{0}var_jobname = {3}{0}var_content = {4}{0}var_contenticon = {5}{0}",
Environment.NewLine,
this.var_jobname,
this.jobType,
this.var_jobname,
this.var_content,
this.var_contenticon );
return foo;
}
Then, before you queue you may:
Console.WriteLine( job1 );