Why can't I get Automapper Parameterization to work - c#

Given the following Automapper profile :
public class MyProfile: Profile
{
private int? _injectedInt;
public MyProfile()
{
CreateMap<objectA, objectB>()
.ForMember(e => e.myNullableInt, x => x.MapFrom(s =>_injectedInt.HasValue ? 100 : 0));
}
}
And the following code :
var result = queryableOfObjectA.ProjectTo<objectB>(new { _injectedInt = 1 });
var resultingValue = result.FirstOrDefault().myNullableInt;
Why is "resultingValue" returning 0 instead of 100?
I can't see what I have done wrong from the docs:
http://docs.automapper.org/en/stable/Queryable-Extensions.html#parameterization

I think the place where _injectedInt is declared might be the issue. I have written following test and 100 is returned.
[TestClass]
public class UnitTest19
{
[TestMethod]
public void TestMethod1()
{
Mapper.Initialize(expression => expression.AddProfile(new MyProfile()));
var queryableOfObjectA = new List<objectA>
{
new objectA
{
myNullableInt = 10
}
};
var result = queryableOfObjectA.AsQueryable().ProjectTo<objectB>(new { _injectedInt = (int?)1 });
var resultingValue = result.FirstOrDefault()?.myNullableInt;
Assert.AreEqual(100, resultingValue);
}
}
public class MyProfile : Profile
{
public MyProfile()
{
int? _injectedInt = null;
CreateMap<objectA, objectB>()
.ForMember(e => e.myNullableInt, x => x.MapFrom(s => _injectedInt.HasValue ? 100 : 0));
}
}
public class objectA
{
public int myNullableInt { get; set; }
}
public class objectB
{
public int myNullableInt { get; set; }
}

Related

Adding custom logics to Mapster's mapping, possibly with AfterMapping?

After mapping Input to Output, the returned Input must have an incrementing number in its Entries[i].Id, (i.e. Entries[0].Id = 1, Entries[1].Id = 2, Entries[2].Id = 3, ...). So I tried to put it in AfterMapping:
[Mapper]
public interface IMyMapper {
Output Map(Input userTableTemplate);
}
public class RegisterMyMapper : IRegister {
public void Register(TypeAdapterConfig config) {
config.NewConfig<Input, Output>()
.Map(output => output.OutputName, input => input.Name)
.AfterMapping(output => {
foreach (var pair in output.Entries.Select((value, index) => new {value = value, index = index})) {
pair.value.Id = pair.index + 1;
}
});
}
}
public class Output {
public string OutputName { get; set; }
public IEnumerable<Entry> Entries { get; set; }
}
public class Entry { public int Id { get; set; } }
public class Input { public string Name { get; set; } }
But when running _myMapper.Map(myInput) I'm getting a null reference exception, because the private Action<Output> Action1 member of the generated code (public partial class MyMapper : IIMyMapper) is null:
public partial class MyMapper : IMyMapper
{
private Action<Output> Action1;
public Output Map(Input p1)
{
if (p1 == null)
{
return null;
}
Output result = new Output();
result.OutputName = p1.Name;
Action1.Invoke(result);
return result;
}
}

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);
}
}

Accessing Moq Mock Data from DbContext disappears when called twice?

I am trying to understand a behavior that is occurring in my application. I have mocked out my DbContext and when I make a call get items from the dbContext.Set<T>().ToList(), the second call does not contain my mocked data. I am not sure why this happens since that data should still exist. Please see code below:
SUT:
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public decimal Salary { get; set; }
}
public class EmployeeDb
: DbContext
{
public EmployeeDb()
{
}
public virtual IDbSet<Employee> Employees { get; set; }
}
UNIT TEST:
public class MockDatabase
{
public Mock<EmployeeDb> SetMockData()
{
var mockDb = new Mock<EmployeeDb>();
mockDb.Setup(i => i.Set<Employee>()).Returns(GetMockSet(Employees).Object);
mockDb.SetupGet(i => i.Employees).Returns(() => GetMockSet(Employees).Object);
return mockDb;
}
private List<Employee> _providers;
private List<Employee> Employees => _providers ?? (_providers = new List<Employee>
{
GetEmployee(1),
GetEmployee(2),
GetEmployee(3),
GetEmployee(4),
GetEmployee(5),
});
private static Employee GetEmployee(int id)
{
return new Employee
{
FirstName = Faker.Name.First(),
LastName = Faker.Name.Last(),
Age = Faker.RandomNumber.Next(50),
Id = id,
Salary = Faker.RandomNumber.Next(100000)
};
}
#region Hood
public static Mock<DbSet<T>> GetMockSet<T>(IList<T> items) where T : class
{
var querable = items.AsQueryable();
var mockSet = new Mock<DbSet<T>>();
mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(querable.Provider);
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(querable.Expression);
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(querable.ElementType);
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(querable.GetEnumerator());
mockSet.Setup(i => i.Add(It.IsAny<T>())).Callback(delegate (T item) {
items.Add(item);
});
return mockSet;
}
#endregion
}
[TestClass]
public class UnitTest1
{
private EmployeeDb _context;
[TestInitialize]
public void TestInitialize()
{
var mockDb = new MockDatabase();
_context = mockDb.SetMockData().Object;
}
[TestMethod]
public void Test_CallTwice_ReturnsEqualCount()
{
var emps = _context.Set<Employee>().ToList();
var emps2 = _context.Set<Employee>().ToList();
Assert.IsTrue(emps.Count == emps2.Count);
// -- This works
//var empCount = _context.Set<Employee>().Count();
//var empCount2 = _context.Set<Employee>().Count();
//Assert.IsTrue(empCount == empCount2);
}
}
Is there something I am not getting about this code? Is there something Moq does with the ToList()?
ToList enumerates the set when invoked, but the enumerator is forward only, so after the first call it is already at the end.
When setting up the GetEnumerator use the function overload of the Returns in order to allow multiple calls other wise the same enumerator will be returned every time and you get the behavior you experienced.
mockSet.As<IQueryable<T>>()
.Setup(m => m.GetEnumerator())
.Returns(() => querable.GetEnumerator()); //<-- function

Mocking adding items to a list in .NET NMock2

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!

Create a fixture for recursive data structure with AutoFixture

I'm working on a project where I have some recursive data structure and I want to create a fixture for it.
The data structure is XmlCommandElement, it has a single method ToCommand that converts XmlCommandElement to Command.
Each node on the tree can be a XmlCommandElement and/or XmlCommandPropertyElement.
Now, in order to test the behaviour of the method ToCommand I want to fetch XmlCommandElement with some arbitrary data.
I want to control the depth of the tree and the amount of instances of XmlCommandElement and/or XmlCommandPropertyElement per node.
So here is the code I'm using for the fixture:
public class XmlCommandElementFixture : ICustomization
{
private static readonly Fixture _fixture = new Fixture();
private XmlCommandElement _xmlCommandElement;
public int MaxCommandsPerDepth { get; set; }
public int MaxDepth { get; set; }
public int MaxPropertiesPerCommand { get; set; }
public XmlCommandElementFixture BuildCommandTree()
{
_xmlCommandElement = new XmlCommandElement();
var tree = new Stack<XmlCommandElementNode>();
tree.Push(new XmlCommandElementNode(0, _xmlCommandElement));
while (tree.Count > 0) {
var node = tree.Pop();
node.Command.Key = CreateRandomString();
node.Command.Properties = CreateProperties();
if (MaxDepth > node.Depth) {
var commands = new List<XmlCommandElement>();
for (var i = 0; i < MaxCommandsPerDepth; i++) {
var command = new XmlCommandElement();
tree.Push(new XmlCommandElementNode(node.Depth + 1, command));
commands.Add(command);
}
node.Command.Commands = commands.ToArray();
}
}
return this;
}
public void Customize(IFixture fixture)
{
fixture.Customize<XmlCommandElement>(c => c.FromFactory(() => _xmlCommandElement)
.OmitAutoProperties());
}
private static string CreateRandomString()
{
return _fixture.Create<Generator<string>>().First();
}
private XmlCommandPropertyElement[] CreateProperties()
{
var properties = new List<XmlCommandPropertyElement>();
for (var i = 0; i < MaxPropertiesPerCommand; i++) {
properties.Add(new XmlCommandPropertyElement {
Key = CreateRandomString(),
Value = CreateRandomString()
});
}
return properties.ToArray();
}
private struct XmlCommandElementNode
{
public XmlCommandElementNode(int depth, XmlCommandElement xmlCommandElement)
{
Depth = depth;
Command = xmlCommandElement;
}
public XmlCommandElement Command { get; }
public int Depth { get; }
}
}
And this is how I'm using it:
xmlCommandElement = new Fixture().Customize(new XmlCommandElementFixture {
MaxDepth = 2,
MaxCommandsPerDepth = 3,
MaxPropertiesPerCommand = 4
}.BuildCommandTree()).Create<XmlCommandElement>();
This works perfectly fine! but the issue I have with it is it isn't generic, the whole point of AutoFixture at least as far as I know is to avoid making specific fixtures.
So what I would really like to do is something like this (found it here but it doesn't work for me.):
var fixture = new Fixture();
fixture.Behaviors.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new DepthThrowingRecursionBehavior(2));
fixture.Behaviors.Add(new OmitOnRecursionForRequestBehavior(typeof(XmlCommandElement), 3));
fixture.Behaviors.Add(new OmitOnRecursionForRequestBehavior(typeof(XmlCommandPropertyElement), 4));
xmlCommandElement = fixture.Create<XmlCommandElement>();
Here is all the code for reference:
Interfaces:
public interface ICommandCollection : IEnumerable<ICommand>
{
ICommand this[string commandName] { get; }
void Add(ICommand command);
}
public interface ICommandPropertyCollection : IEnumerable<ICommandProperty>
{
string this[string key] { get; }
void Add(ICommandProperty property);
}
public interface ICommandProperty
{
string Key { get; }
string Value { get; }
}
public interface ICommand
{
ICommandCollection Children { get; set; }
string Key { get; }
ICommandPropertyCollection Properties { get; }
}
public interface ICommandConvertible
{
ICommand ToCommand();
}
Classes:
public sealed class CommandPropertyCollection : ICommandPropertyCollection
{
private readonly IDictionary<string, ICommandProperty> _properties;
public CommandPropertyCollection()
{
_properties = new ConcurrentDictionary<string, ICommandProperty>();
}
public string this[string key]
{
get
{
ICommandProperty property = null;
_properties.TryGetValue(key, out property);
return property.Value;
}
}
public void Add(ICommandProperty property)
{
_properties.Add(property.Key, property);
}
public IEnumerator<ICommandProperty> GetEnumerator()
{
return _properties.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public sealed class CommandProperty : ICommandProperty
{
public CommandProperty(string key, string value)
{
Key = key;
Value = value;
}
public string Key { get; }
public string Value { get; }
}
public sealed class Command : ICommand
{
public Command(string key, ICommandPropertyCollection properties)
{
Key = key;
Properties = properties;
}
public ICommandCollection Children { get; set; }
public string Key { get; }
public ICommandPropertyCollection Properties { get; }
}
public class XmlCommandPropertyElement : ICommandPropertyConvertible
{
[XmlAttribute("key")]
public string Key { get; set; }
[XmlAttribute("value")]
public string Value { get; set; }
public ICommandProperty ToCommandProperty()
{
return new CommandProperty(Key, Value);
}
}
Finally, the class I'm trying to test is as follow:
public class XmlCommandElement : ICommandConvertible
{
[XmlArray]
[XmlArrayItem("Command", typeof(XmlCommandElement))]
public XmlCommandElement[] Commands { get; set; }
[XmlAttribute("key")]
public string Key { get; set; }
[XmlArray]
[XmlArrayItem("Property", typeof(XmlCommandPropertyElement))]
public XmlCommandPropertyElement[] Properties { get; set; }
public ICommand ToCommand()
{
ICommandPropertyCollection properties = new CommandPropertyCollection();
foreach (var property in Properties) {
properties.Add(property.ToCommandProperty());
}
ICommand command = new Command(Key, properties);
return command;
}
}
The test itself looks like this:
namespace Yalla.Tests.Commands
{
using Fixtures;
using FluentAssertions;
using Ploeh.AutoFixture;
using Xbehave;
using Yalla.Commands;
using Yalla.Commands.Xml;
public class XmlCommandElementTests
{
[Scenario]
public void ConvertToCommand(XmlCommandElement xmlCommandElement, ICommand command)
{
$"Given an {nameof(XmlCommandElement)}"
.x(() =>
{
xmlCommandElement = new Fixture().Customize(new XmlCommandElementFixture {
MaxDepth = 2,
MaxCommandsPerDepth = 3,
MaxPropertiesPerCommand = 4
}.BuildCommandTree()).Create<XmlCommandElement>();
});
$"When the object is converted into {nameof(ICommand)}"
.x(() => command = xmlCommandElement.ToCommand());
"Then we need to have a root object with a key"
.x(() => command.Key.Should().NotBeNullOrEmpty());
"And 4 properties as its children"
.x(() => command.Properties.Should().HaveCount(4));
}
}
}
Thanks to Mark Seemann! the final solution looks like this:
public class RecursiveCustomization : ICustomization
{
public int MaxDepth { get; set; }
public int MaxElements { get; set; }
public void Customize(IFixture fixture)
{
fixture.Behaviors
.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new OmitOnRecursionBehavior(MaxDepth));
fixture.RepeatCount = MaxElements;
}
}
And can be used like this:
xmlCommandElement = new Fixture().Customize(new RecursiveCustomization {
MaxDepth = 2,
MaxElements = 3
}).Create<XmlCommandElement>();
You can fairly easily create a small tree by changing the Fixture's recursion behaviour:
[Fact]
public void CreateSmallTree()
{
var fixture = new Fixture();
fixture.Behaviors
.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new OmitOnRecursionBehavior(recursionDepth: 2));
var xce = fixture.Create<XmlCommandElement>();
Assert.NotEmpty(xce.Commands);
}
The above test passes.

Categories

Resources