Mocking adding items to a list in .NET NMock2 - c#

I'm using NMock2 (2.1.3641.27570) in my unit tests.
IList<MyObj> values = _mock.NewMock<IList<MyObj>>();
That mock I return when my tested object calls the Values get property on my mocked object:
Expect.AtLeastOnce.On(_myKeepMock).GetProperty("Values").Will(Return.Value(values));
Then I expect value which is a MyObj to be added to my list values:
Expect.AtLeastOnce.On(values).Method("Add").With(value);
In order to avoid unexpected invocation of list'1.Add upon execution I understand I have to override the Equals method in the MyObj class:
public override bool Equals(object obj) { ...}
and compare by value instead of reference. But it doesn't even get called when executing the test (breakpoint not hit).
What do I need to do in order to pass the test when the item added to the list in the call is equal in value to the one added by the tested object?
I read about custom matchers but not sure if those apply here.
UPDATE
Full example:
using System.Collections.Generic;
using System.Linq;
using NMock2;
using NUnit.Framework;
public class Data
{
public int Val { get; set; }
public Data(int val) { Val = val; }
}
public class ModData
{
public int Val { get; set; }
protected bool Equals(ModData other)
{
return this.Val.Equals(other.Val);
}
public override int GetHashCode()
{
return this.Val.GetHashCode();
}
public override bool Equals(object obj)
{
ModData m = (ModData)obj;
return m != null && this.Val == m.Val;
}
}
public interface IAllData
{
IList<Data> Data { get; set; }
IList<ModData> ModData { get; set; }
}
public class AllData : IAllData
{
public IList<Data> Data { get; set; }
public IList<ModData> ModData { get; set; }
}
public class Calco
{
private IAllData _allData;
public Calco(IAllData allData)
{
_allData = allData;
}
public void Sum()
{
_allData.ModData.Add(new ModData { Val = _allData.Data.Sum(d => d.Val) });
}
}
public class CalcoTest
{
[Test]
public void Test()
{
Mockery mockery = new Mockery();
IList<Data> data = new List<Data>();
IList<ModData> modData = mockery.NewMock<IList<ModData>>();
IAllData allData = mockery.NewMock<IAllData>();
ModData modDatum = new ModData { Val = 4 };
data.Add(new Data(1));
data.Add(new Data(10));
Calco c = new Calco(allData);
Expect.AtLeastOnce.On(allData).GetProperty("Data").Will(Return.Value(data));
Expect.AtLeastOnce.On(allData).GetProperty("ModData").Will(Return.Value(modData));
Expect.AtLeastOnce.On(modData).Method("Add").With(modDatum);
c.Sum();
mockery.VerifyAllExpectationsHaveBeenMet();
}
}
Output:
NMock2.Internal.ExpectationException : unexpected invocation of list`1.Add(<WRM.Common.RiskCalculation.Tests.ModData>)
Expected:
at least 1 time: allData.Data, will return <System.Collections.Generic.List`1[WRM.Common.RiskCalculation.Tests.Data]> [called 1 time]
at least 1 time: allData.ModData, will return <list`1> [called 1 time]
at least 1 time: list`1.Add(equal to <WRM.Common.RiskCalculation.Tests.ModData>) [called 0 times]
Notice how it expects invocation of list'1.Add(<WRM.Common.RiskCalculation.Tests.ModData>)
and then shows it didn't call list'1.Add(<WRM.Common.RiskCalculation.Tests.ModData>)

Custom Matchers ARE the answer: http://nmock.sourceforge.net/advanced.html
public class IsMod
{
public static Matcher Equal(ModData otherMod)
{
return new ModMatcher(otherMod);
}
}
internal class ModMatcher : Matcher
{
private readonly ModData _mod;
public ModMatcher(ModData mod)
{
_mod = mod;
}
public override bool Matches(object o)
{
ModData m = (ModData)o;
return _mod.Val.Equals(m.Val);
}
public override void DescribeTo(TextWriter writer)
{
writer.Write("Value same ");
writer.Write(_mod.Val);
}
}
And then
Expect.AtLeastOnce.On(modData).Method("Add").With(IsMod.Equal(modDatum));
Done!

Related

Auto calculate property within class

I have these two classes:
public class LeadPerformanceItem
{
public string name { get; set; }
public int visitors { get; set; }
public decimal visitorspercentoftotal
{
get
{
// ?
}
}
}
public class LeadPerformanceItemCollection
{
public List<LeadPerformanceItem> items {get;set;}
public int totalvisitors
{
get
{
return items.Sum(x => x.visitors);
}
}
}
Is there anyway my visitorspercentoftotal property could be automatically calculated as items are added and removed from the collection?
public class LeadPerformanceItem
{
public string name { get; set; }
public int Visitors { get; set; }
private int _totalVisitors = 0;
public void UpdateTotalVisitors(int total)
{
this._totalVisitors = total;
}
public decimal Visitorspercentoftotal => _totalVisitors != 0
? Convert.ToDecimal(Math.Round(((double) (Visitors * 100)) / _totalVisitors))
: 0;
}
public class LeadPerformanceItemCollection
{
public List<LeadPerformanceItem> Items { get; set; }
public void AddToItems(LeadPerformanceItem item)
{
Items.Add(item);
var total = Items.Sum(x => x.Visitors);
Items.AsParallel().ForAll(i => i.UpdateTotalVisitors(total));
}
public int totalvisitors
{
get { return Items.Sum(x => x.Visitors); }
}
}
[TestFixture]
public class Class1
{
[Test]
public void Test()
{
var leadPerformanceItemCollection = new LeadPerformanceItemCollection();
leadPerformanceItemCollection.Items=new List<LeadPerformanceItem>();
leadPerformanceItemCollection.AddToItems(new LeadPerformanceItem()
{
name = "test",
Visitors = 10
});
leadPerformanceItemCollection.AddToItems(new LeadPerformanceItem()
{
name = "test2",
Visitors = 25
});
Console.WriteLine(leadPerformanceItemCollection.Items[0].Visitorspercentoftotal);
Console.WriteLine(leadPerformanceItemCollection.Items[1].Visitorspercentoftotal);
}
}
result:
29%
71%
One way would be to inherit from List and hide the Add method and create your own and do the calculation there.
public class LeadPerformanceItemCollection : List<LeadPerformanceItem>
{
public new void Add(LeadPerformanceItem item)
{
//calculate percent of total here
base.Add(item);
}
}

How to check if an object has default values in C#

I have an object that I want to check whether it contains default values or not, in the below code but that doesn't cut it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
MyClass obj1 = new MyClass();
MyClass obj2 = null;
if(obj1 == new MyClass())
Console.WriteLine("Initialized");
if(Object.ReferenceEquals(obj1, new MyClass()))
Console.WriteLine("Initialized");
}
}
}
public class MyClass
{
public int Value {get; set; }
public MyClass()
{
this.Value = 10;
}
}
I have also used Object.ReferenceEquals() but that doesn't cut it as well.
This is the fiddle I am working on.
Is there a way to check whether an object contains default values, or if the object is empty?
Edit: In case of an newly initialized object with many nested properties, how to check whether they contain a default value or not?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
MyClass obj1 = new MyClass();
MyClass obj2 = null;
if(obj1 == new MyClass())
Console.WriteLine("Initialized");
if(Object.ReferenceEquals(obj1, new MyClass()))
Console.WriteLine("Initialized");
}
}
}
public class MyClass
{
public int Value {get; set; }
public MyNestedClass MyProperty { get; set; }
public MyClass()
{
this.Value = 10;
this.MyProperty = new MyNestedClass();
}
}
public class MyNestedClass
{
public string SomeStringProperty { get; set; }
public MyNestedClass()
{
this.SomeStringProperty = "Some string";
}
}
Here is the fiddle in the case of nested objects.
You can achieve your goal by overriding Equals and GetHashCode, creating and saving an immutable "default" instance, and comparing the value to it:
public class MyClass {
public static readonly MyClass DefaultInstance = new MyClass();
public int Value { get; set; }
public MyClass() {
this.Value = 10;
}
public override int GetHashCode() {
return Value.GetHashCode();
}
public override bool Equals(Object obj) {
if (obj == this) return true;
var other = obj as MyClass;
return other?.Value == this.Value;
}
}
Now you can check if the instance is equal to a newly created one by calling
if (MyClass.DefaultInstance.Equals(instanceToCheck)) {
... // All defaults
}
You can change what it means for an instance to be "default" by altering DefaultInstance object.
Note: this trick works well only with immutable MyClass. Otherwise some code could perform MyClass.DefaultInstance.Value = 20 and change the "default" object.
Here is one method using JSON serialization that allows you to check if the objects are equal or not:
DotNetFiddle:
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var defaultObj = new MasterObject();
var notDefaultObject = new MasterObject();
var defaultJson = JsonConvert.SerializeObject(defaultObj);
var notDefaultJson = JsonConvert.SerializeObject(notDefaultObject);
Console.WriteLine("First Test");
if (defaultJson == notDefaultJson)
Console.WriteLine("Same thing");
else
Console.WriteLine("Not same thing");
notDefaultObject.Sub1.SomeObject.SomeOtherValue = "Not a default Value";
notDefaultJson = JsonConvert.SerializeObject(notDefaultObject);
Console.WriteLine("Second Test");
if (defaultJson == notDefaultJson)
Console.WriteLine("Same thing");
else
Console.WriteLine("Not same thing");
}
}
public class MasterObject
{
public SubObject1 Sub1 { get; set; }
public SubObject2 Sub2 { get; set; }
public string SomeString { get; set; }
public MasterObject()
{
Sub1 = new SubObject1();
Sub2 = new SubObject2();
SomeString = "Some Default String";
}
}
public class SubObject1
{
public string SomeValue { get; set; }
public SubObject2 SomeObject { get; set; }
public SubObject1()
{
SomeObject = new SubObject2();
SomeValue = "Some other Default String";
}
}
public class SubObject2
{
public string SomeOtherValue { get; set; }
public SubObject2()
{
SomeOtherValue = "Some default";
}
}
Output:
First Test
Same thing
Second Test
Not same thing
What is happening is that you serialize the default object and then you make changes to the "not default object", re-serialize and compare again. This can be slow because you are generating strings, but as long as all the sub-objects can be serialized this will be the simplest way to compare if an object is "default" (what you get from new) or has been modified.

Passing property as object to method

I would like to build a helper method which will take property as object to anonymous method. This is just dummy code example to visualize problem not confront real solution which is way more complex and is not subject of this question.
Some reference code:
public class FooClass : SomeBaseClass {
public string StringProperty { get; set; }
public int IntProperty { get; set; }
public DateTime DateTimeProperty { get; set; }
public Object ComplexObjectProperty { get; set; }
public FooClass() {
this.FooMethod(this.StringProperty);
this.FooMethod(this.IntProperty);
this.FooMethod(this.DateTimeProperty);
this.FooMethod(this.ComplexObjectProperty);
}
public void FooMethod<T>(T obj) {
Func<bool> validateMethod = () => {
if(obj is string) return string.IsNullOrEmpty(obj.ToString());
return obj != null;
};
this.ValidateMethodsAggregate.Add(validateMethod);
}
}
public class SomeBaseClass {
protected IList<Func<bool>> ValidateMethodsAggregate = new List<Func<bool>>();
public void ValidateAll() {
foreach (var validateMethod in this.ValidateMethodsAggregate) {
var result = validateMethod();
// has errors and so on handling...
}
}
}
// Some simple code to show use case.
var foo = new FooClass();
foo.StringProperty = "new value";
foo.IntProperty = 123;
foo.ValidateAll(); // this will use "" , 0 instead of new values.
Use a function and a conditional operator with a private backing method
public FooClass()
{
this.FooMethod(() => StringProperty); // <- pass an accessor
}
public Func<bool> validateMethod;
private void FooMethod<T>(Func<T> obj)
{
//validate method
validateMethod = () => string.IsNullOrEmpty(obj()?.ToString());
}
The usage would be
var y = new FooClass();
var resTrue = y.validateMethod();
y.StringProperty = "Hi";
var resFalse = y.validateMethod();

Using LINQ: How To Return Array Of Properties from a Class Collection?

Here is a Basic Class with TheProperty in question:
class BasicClass {
public BasicClass() {
TheProperty = new Object();
Stamped = DateTime.Now;
}
public object TheProperty { get; set; }
public DateTime Stamped { get; private set; }
}
Here is the Basic List:
class BasicList {
private List<BasicClass> list;
public BasicList() {
list = new List<BasicClass>();
}
public BasicClass this[object obj] {
get { return list.SingleOrDefault(o => o.TheProperty == obj); }
}
public void Add(BasicClass item) {
if (!Contains(item.TheProperty)) {
list.Add(item);
}
}
public bool Contains(object obj) {
return list.Any(o => o.TheProperty == obj); // Picked this little gem up yesterday!
}
public int Count { get { return list.Count; } }
}
I'd like to add a class to BasicList that will return an array of items.
I could write it like this, using traditional C#:
public object[] Properties() {
var props = new List<Object>(list.Count);
foreach (var item in list) {
props.Add(item.TheProperty);
}
return props.ToArray();
}
...but how would I write that using a LINQ or Lambda query?
return list.Select(p=>p.TheProperty).ToArray()

How can I set default value to exceptions in automapper while mapping from string to int type property?

I am trying to map one object to another but I am getting a problem while mapping an empty string to type int or a non integer string to int, so what I want that if I such exceptions occur it must assign some default value to it, let say -1.
for example we have a class A and Class B
Class A
{
public string a{get;set;}
}
Class B
{
public int a{get;set;}
}
Now if we map from class A to B using default rule it will through exception if string is empty or non integer.
Please help me fix this problem.
Thanks in advance.
I think this is what you're after.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using NUnit.Framework;
namespace StackOverFlowAnswers
{
public class LineItem
{
public int Id { get; set; }
public string ProductId { get; set; }
public int Amount { get; set; }
}
public class Model
{
public int Id { get; set; }
public string ProductId { get; set; }
public string Amount { get; set; }
}
public class AutoMappingTests
{
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
Mapper.CreateMap<Model, LineItem>()
.ForMember(x => x.Amount, opt => opt.ResolveUsing<StringToInteger>());
}
[Test]
public void TestBadStringToDefaultInteger()
{
// Arrange
var model = new Model() {Id = 1, ProductId = "awesome-product-133-XP", Amount = "EVIL STRING, MWUAHAHAHAH"};
// Act
LineItem mapping1 = Mapper.Map<LineItem>(model);
// Assert
Assert.AreEqual(model.Id, mapping1.Id);
Assert.AreEqual(model.ProductId, mapping1.ProductId);
Assert.AreEqual(0, mapping1.Amount);
// Arrange
model.Amount = null; // now we test null, which we said in options to map from null to -1
// Act
LineItem mapping2 = Mapper.Map<LineItem>(model);
// Assert
Assert.AreEqual(-1, mapping2.Amount);
}
}
public class StringToInteger : ValueResolver<Model, int>
{
protected override int ResolveCore(Model source)
{
if (source.Amount == null)
{
return -1;
}
int value;
if (int.TryParse(source.Amount, out value))
{
return value; // Wahayy!!
}
return 0; // return 0 if it could not parse!
}
}
}
Well the above code works too while i am sharing one code which i made myself as it works too
public class StringToIntTypeConverter : ITypeConverter<string, int>
{
public int Convert(ResolutionContext context)
{
int result;
if (!int.TryParse(context.SourceValue.ToString(), out result))
{
result = -1;
};
return result;
}
}

Categories

Resources