Moq callback caching stale variable value - c#

I have this sample code snippet below.
The Test_MailIt test method fails with the error
'Assert.AreEqual failed. Expected:<0>. Actual:<7>. '
I would expect it to pass because I'd expect the testMailItem to be 0 the first time ReusableMethod is called, and 7 the second time ReusableMethod is called.
However it seems that the callback has somehow cached testMailItem value from the first time it was called.
public interface IMyWebSocket
{
public void send(int a);
}
public class PostMan
{
IMyWebSocket socket;
public PostMan(IMyWebSocket _socket)
{
this.socket = _socket;
}
public void MailIt(int mailItem)
{
this.socket.send(mailItem);
}
}
[TestClass]
public class MyTestClass
{
[TestMethod]
public void Test_MailIt()
{
int testMailItem = 0;
PostMan p = ReusableMethod(testMailItem, null);
testMailItem = 7;
PostMan p1 = ReusableMethod(testMailItem, p);
}
private PostMan ReusableMethod(int testMailItem, PostMan p=null )
{
if (p==null)
{
Mock<IMyWebSocket> obj = new Mock<IMyWebSocket>();
obj.Setup(x => x.send(It.IsAny<int>())).Callback<int>((x) => { Assert.AreEqual(testMailItem, x); });
p = new PostMan(obj.Object);
}
p.MailIt(testMailItem);
return p;
}
}
Is this behavior expected ? The aim here is not to refactor to get this to work, but to understand why the callback is unable to use testMailItem as passed to ReusableMethod the second time.

I altered the way I was testing, and I was able to verify the parameters. I essentially used an object to wrap the value to be verified.
public class VerifiableObject
{
public int val;
public VerifiableObject(int _val)
{
this.val = _val;
}
}
[TestClass]
public class MyTestClass
{
[TestMethod]
public void Test_MailIt()
{
int testMailItem = 0;
VerifiableObject v = new VerifiableObject(testMailItem);
PostMan p = ReusableMethod(v, null);
testMailItem = 7;
v.val = testMailItem;
PostMan p1 = ReusableMethod(v, p);
}
private PostMan ReusableMethod(VerifiableObject testMailItem, PostMan p = null)
{
if (p == null)
{
Mock<IMyWebSocket> obj = new Mock<IMyWebSocket>();
obj.Setup(x => x.send(It.IsAny<int>())).Callback<int>((x) => { Assert.AreEqual(testMailItem.val, x); });
p = new PostMan(obj.Object);
}
p.MailIt(testMailItem.val);
return p;
}
}

Related

unit test case returning null while unit testing

I have a below method which simply unnest the list within list and and create merged record all sub lists
e.g.
testResultDTO similar to
{
dept_name :'',
dept_id:'',
personList :'<List>'
}
personList is list similat to
{
first_name :'',
Last_name:'',
workHistList:'<List>'
}
workHistList is similar to
{
task_name:'',
task_description:''}
`
And the method is below
public async Task<FileDTO> GetWorkList(InputParameter inputParameter)
{
TestResultDTO testResultDTO = await GetPersonWorkList(inputParameter);
var testDto = new List<TestDto>();
if (testResultDTO != null)
{
testDto = personWorkFile(testResultDTO);
}
return testDto;
}
The problem is in method personWorkFile
private List<testDTO> personWorkFile(testResultDTO testResultDTO)
{
List<testDTO> testDTO = new List<testDTO>();
if (testResultDTO.workList is null) return new();
foreach (var testItem in testResultDTO.workList)
{
if (testItem.personList != null && testItem.personList.Any())
{
for (var j = 0; j < testItem.personList.Count; j++)
{
List<testDTO> testDTOTemp = new List<testDTO>();
for (var i = 0; i < testItem.personList[j].workHistList.Count; i++)
{
testDTOTemp.Insert(i, mapper.Map(testItem.personList[j].workHistList[i], mapper.Map<testDTO>(testItem.personList[j])));
}
testDTO.AddRange(testDTOTemp);
}
}
}
return testDTO;
}
`
what it does is it create a finale list with record similar to
{dept_name,dept_id,first_name, last_name, task_name, task_description}
Now when i create a unit test for it, it always fail because, it always insert null in list testDTOTemp.insert
my content of test case code is below
mapperMock.Setup(m => m.Map<List<TestResultDTO>, List<TestDTO>>(testResultDTO)).Returns(testDTO);
//call actual service
var result = await workService.GetWorkList(inputParameter);
Can someone please help me understand why it is not able to insert any data testDTOTemp list
The mock replays the setup by matching the method arguments. In this particular case, it will try to match the method call with the specified instance of TestResultDTO.
Override the Equals() method in TestResultDTO to let the mock compare the argument in order to return as per the setup.
Ex:
public class TestResultDTO
{
public int Id {get; set;}
}
var dto01 = new TestResultDTO(){Id = 1};
var dto02 = new TestResultDTO(){Id = 1};
dto01.Equals(dto02); // This will result in false in spite of having same Ids
If the above class is modified to
public class TestResultDTO
{
public int Id {get; set;}
public override bool Equals(object other)
{
var right = other as TestResultDTO;
if(right == null) return false;
var left = this;
var result = left.Id == right.Id;
return result;
}
}
var dto01 = new TestResultDTO(){Id = 1};
var dto02 = new TestResultDTO(){Id = 1};
dto01.Equals(dto02); // This will result in true

Getting the callstack from a method 'A' (MethodBase/MethodInfo) being called from 'B' or 'C' without the stacktrace

Well, I would like to do my own benchmarking system like spark in Minecraft (https://github.com/lucko/spark):
I'm using Harmony lib (https://github.com/pardeike/Harmony) which allows me to interact/modify methods and allows me to add a Prefix/Postfix on each call that will help me out with this stack.
The basic structure has something similar to (https://github.com/pardeike/Harmony/issues/355):
[HarmonyPatch]
class MyPatches
{
static IEnumerable<MethodBase> TargetMethods()
{
return AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly())
.SelectMany(type => type.GetMethods())
.Where(method => method.ReturnType != typeof(void) && method.Name.StartsWith("Do"));
}
static void Prefix(out Stopwatch __state, MethodBase __originalMethod)
{
__state = Stopwatch.StartNew();
// ...
}
static void Postfix(Stopwatch __state, MethodBase __originalMethod)
{
__state.Stop();
// ....
}
}
The problem here is that the __originalMethod doesn't take care if it was called from A or B.
So for example, we had patched string.Join method. And the we call from A or B, where A or B, is the full callstack of this method.
So first, we need to assign a ID to this call, and we need to create a Tree-based structure (which is hard to serialize later), from here (https://stackoverflow.com/a/36649069/3286975):
public class TreeModel : Tree<TreeModel>
{
public int ID { get; set; }
public TreeModel() { }
public TreeModel(TreeModel parent) : base(parent) { }
}
public class Tree<T> where T : Tree<T>
{
protected Tree() : this(null) { }
protected Tree(T parent)
{
Parent=parent;
Children=new List<T>();
if(parent!=null)
{
parent.Children.Add(this as T);
}
}
public T Parent { get; set; }
public List<T> Children { get; set; }
public bool IsRoot { get { return Parent==null; } }
public T Root { get { return IsRoot?this as T:Parent.Root; } }
public T RecursiveFind(Predicate<T> check)
{
if(check(this as T)) return this as T;
foreach(var item in Children)
{
var result=item.RecursiveFind(check);
if(result!=null)
{
return result;
}
}
return null;
}
}
Now, the thing is that we need to fill the Tree as long as we iterate all the method and instructions got from Harmony. Forget about Harmony for a second, I will explain only two facts about it.
The lib allows you first to get all patched methods through IEnumerable<MethodBase> TargetMethods() so, you have the Assembly X passed through reflection and filtered all methods that are allowed to be patched (some of them broke Unity, so I decided to skip methods from UnityEngine., UnityEditor. and System.* namespaces).
And we have also the ReadMethodBody method (https://harmony.pardeike.net/api/HarmonyLib.PatchProcessor.html#HarmonyLib_PatchProcessor_ReadMethodBody_System_Reflection_MethodBase_) from a given MethodBase it returns all IL stack instructions.
So we can start to iterate over and over in order to get all instructions and fill the entire tree. This is what I wrote last night:
internal static class BenchmarkEnumerator
{
internal static Dictionary<MethodBase, int> Mappings { get; } = new Dictionary<MethodBase, int>();
internal static Dictionary<int, TreeModel> TreeIDs { get; } = new Dictionary<int, TreeModel>();
internal static Dictionary<MethodBase, BenchmarkTreeModel> TreeMappings { get; } = new Dictionary<MethodBase, BenchmarkTreeModel>();
private static HashSet<int> IDUsed { get; } = new HashSet<int>();
public static int GetID(this MethodBase method)
{
return GetID(method, out _);
}
public static int GetID(this MethodBase method, out bool contains)
{
// A > X = X1
// B > X = X2
if (!Mappings.ContainsKey(method))
{
var id = Mappings.Count;
Mappings.Add(method, Mappings.Count);
IDUsed.Add(id);
contains = false;
return id;
}
contains = true;
return Mappings[method];
}
public static int GetFreeID()
{
int id;
Random rnd = new Random();
do
{
id = rnd.Next();
} while (IDUsed.Contains(id));
IDUsed.Add(id);
return id;
}
public static BenchmarkCall GetCall(int id)
{
return TreeIDs[id]?.Call;
}
public static BenchmarkCall GetCall(this MethodBase method)
{
return TreeIDs[Mappings[method]]?.Call;
}
}
The BenchmarkEnumerator class allow us to differentiate between A or B, but it doesn't care about the full hierarchy, only from the parent MethodBase itself, so I need to write something complex to take in care of the full call stack, which I said I have a problem to understand.
Then we have the TargetMethods:
private static IEnumerable<MethodBase> TargetMethods()
{
Model = new BenchmarkTreeModel();
var sw = Stopwatch.StartNew();
//int i = 0;
return Filter.GetTargetMethods(method =>
{
try
{
var instructions = PatchProcessor.ReadMethodBody(method);
var i = method.GetID(out var contains);
var tree = new TreeModel
{
ID = i
};
if (contains)
{
//var lastId = i;
i = GetFreeID();
tree.ID = i;
tree.FillMethodName($"{method.GetMethodSignature()}_{i}"); // TODO: Check this
tree.Parent = null;
tree.Children = TreeMappings[method].Forest.First().Children; // ??
//DictionaryHelper.AddOrAppend(TreeMappings, method, tree);
TreeMappings[method].Forest.Add(tree);
TreeIDs.Add(i, tree);
Model.Forest.Add(tree);
// UNIT TESTING: All contained methods at this point will have a parent.
// string.Join is being added as a method by a instruction, so when we try to patch it, it will have already a reference on the dictionary
// Here, we check if the method was already added by a instruction CALL
// Logic: If the method is already contained by the mapping dictionary
// then, we will exit adding a new that will have the same childs but a new ID
return false;
}
TreeIDs.Add(i, tree);
tree.FillMethodName($"{method.GetMethodSignature()}_{i}"); // TODO: Check this
foreach (var pair in instructions)
{
var opcode = pair.Key;
if (opcode != OpCodes.Call || opcode != OpCodes.Callvirt) continue;
var childMethod = (MethodBase)pair.Value;
var id = childMethod.GetID(out var _contains);
var subTree = new TreeModel(tree)
{
ID = id
};
if (_contains)
{
id = GetFreeID();
subTree.ID = id;
subTree.FillMethodName($"{childMethod.GetMethodSignature()}_{id}"); // TODO: Check this
subTree.Parent = TreeIDs[i];
subTree.Children = TreeMappings[childMethod].Forest.First().Children;
TreeIDs.Add(id, subTree);
continue;
}
TreeIDs.Add(id, subTree);
subTree.FillMethodName($"{childMethod.GetMethodSignature()}_{id}");
tree.Children.Add(subTree);
TreeMappings.Add(childMethod, new BenchmarkTreeModel());
TreeMappings[childMethod].Forest.Add(subTree);
}
TreeMappings.Add(method, new BenchmarkTreeModel());
TreeMappings[method].Forest.Add(tree);
Model.Forest.Add(tree);
return true;
//var treeModel = new TreeModel();
}
catch (Exception ex)
{
//Debug.LogException(new Exception(method.GetMethodSignature(), ex));
return false;
}
}, sw);
//return methods;
}
The GetMethodSignature is something like:
public static string GetMethodSignature(this MethodBase method)
{
if (method == null) return null;
return method.DeclaringType == null ? method.Name : $"{method.DeclaringType.FullName}.{method.Name}";
}
I think I'll replace it with the MethodBase.ToString instead (what do you think?)
Also, we have the BenchmarkCall class which allow us to take in care how many times the call was done and how many time it has spent at all:
[Serializable]
public class BenchmarkCall
{
public string Method { get; set; }
public double SpentMilliseconds { get; set; }
public long SpentTicks { get; set; }
public double MinSpentMs { get; set; } = double.MaxValue;
public double MaxSpentMs { get; set; } = double.MinValue;
public long MinSpentTicks { get; set; } = long.MaxValue;
public long MaxSpentTicks { get; set; } = long.MinValue;
public double AvgMs => SpentMilliseconds / TimesCalled;
public double AvgTicks => SpentTicks / (double)TimesCalled;
public BenchmarkCall()
{
}
public BenchmarkCall(MethodBase method)
{
Method = method.GetMethodSignature();
}
public override string ToString()
{
if (TimesCalled > 0)
return "BenchmarkCall{\n" +
$"Ticks[SpentTicks={SpentTicks},MinTicks={MinSpentTicks},MaxTicks={MaxSpentTicks},AvgTicks={AvgTicks:F2}]\n" +
$"Ms[SpentMs={SpentMilliseconds:F2},MinMs={MinSpentMs:F2},MaxMs={MaxSpentMs:F2},AvgMs={AvgMs:F2}]\n" +
"}";
return "BenchmarkCall{}";
}
}
}
So I think that my next movement will be to differentiate between X method being called from A or B (Xa or Xb) taking care of the full hierarchy (which I'm not sure how to do) instead of the parent method that calls it, maybe the code I wrote has some to do it with it, but I'm not sure (last night I was so tired, so I didn't code it taking care those facts), build up a list of method signatures with different IDs, and then fill up the tree, ID 1 is Xa and ID 2 is Xb (where I have problems also filling up the tree).
Also I'll need to use the Transpiler in order to alter all code instructions, so if a method has:
void method() {
X1();
X2();
}
We will need to add 2 methods (like prefix/postfix) to measure each instruction call:
void method() {
Start(1);
X1();
End(1);
Start(2);
X2();
End(2);
}
This will be a hard task, but I hope somebody could guide me with this out.

Xunit test not working for mongodb service

I want to make a small XUnit test but it is not working. (AddTest is working but GetAllRestaurantsCountShouldReturnThree not working. )
I am new to unit testing and I don't know about Moq and how to use it.
How can I mock my IMongoService and get restaurant count?
MongoService.cs
public class MongoService : IMongoService
{
private readonly IMongoDatabase _mongoDatabase;
private readonly IMongoClient _mongoClient;
public MongoService()
{
_mongoClient = new MongoClient("mongodb://localhost:27017");
_mongoDatabase = _mongoClient.GetDatabase("Restaurant");
}
public List<RestaurantDto> GetAllRestaurants()
{
var collection = _mongoDatabase.GetCollection<RestaurantDto>("Restaurant");
return collection.Find(_ => true).ToList();
}
}
MongoServiceTest.cs
public class ReviewServiceTests
{
private List<RestaurantDto> _allRestaurants = new List<RestaurantDto>()
{
new RestaurantDto() {Name="xxx", ZipCode = "111" },
new RestaurantDto() {Name="yyy", ZipCode = "222" },
new RestaurantDto() {Name="zzz", ZipCode = "333" },
};
[Fact] //Not Working
public void GetAllRestaurantsCountShouldReturnThree()
{
var _mongoService = new Mock<IMongoService>();
_mongoService.Setup(x => x.GetAll()).Returns(_allRestaurants );
var count = _mongoService.GetAll(); //GetAll() not seeing
Assert.Equal(count, 3);
}
[Fact] //Working
public void AddTest()
{
Assert.Equal(10, Add(8, 2));
}
int Add(int a, int b)
{
return a + b;
}
}
You are using Moq incorrectly
[Fact]
public void GetAllRestaurantsCountShouldReturnThree() {
var mock = new Mock<IMongoService>();
mock.Setup(x => x.GetAllRestaurants()).Returns(_allRestaurants);
IMongoService mongoService = mock.Object;
var items = mongoService.GetAllRestaurants(); //Should call mocked service;
var count = items.Count;
Assert.Equal(count, 3);
}
Read up on the how to use Moq in their Quickstart

500 Internal Server Error for Store Method

I am gettin an null reference exception inside the Controller on the line:
return await Store.GetSearchDTO();
The error in the console reads:
POST http://localhost:55471/api/GetSearchDTO 500 (Internal Server Error)
Error: Resolving failed with a reason [object Object], but no resolveFailed provided for segment Search
Any insight on why this may be happening would be great.
Controller
namespace Api.Controllers
{
[Authorize]
[RoutePrefix("api/Search")]
public class Controller : ApiController
{
private Store _store;
public Store Store
{
get
{
return _store ?? Request.GetOwinContext().Get<Store>();
}
private set
{
_store = value;
}
}
public Controller()
{
}
public Controller(Store store)
{
Store = store;
}
[HttpPost]
[Route("GetSearchDTO")]
public async Task<SearchDTO> GetSearchDTO()
{
return await Store.GetSearchDTO();
}
}
}
Store
public async Task<SearchDTO> GetSearchDTO()
{
var toReturn = new SearchDTO();
var assessment = await Db.Definitions.Where(x => x.IsActive == true).ToListAsync();
var Types = await Db.Types.ToListAsync();
int i = 0;
int j = 0;
foreach(var assess in assessment)
{
var courseName = await Db.Courses.Where(x => x.Id == assess.CourseId).FirstOrDefaultAsync();
toReturn.CourseIds[i] = courseName.Id;
toReturn.CourseNames[i] = courseName.Name;
toReturn.Names[i] = assess.Name;
i++;
}
foreach(var type in Types)
{
toReturn.TypeIds[j] = type.Id;
toReturn.Types[j] = type.Name;
}
toReturn.SectionFlag = true;
return toReturn;
}
}
}

Entity framework error as"New transaction is not allowed because there are other threads running in the session

We are using entity framework codefirst approach
I am new to entity framework and I am facing error while trying to do "New transaction is not allowed because there are other threads running in the session.
public class DatabaseBackup : IDataBackup
{
private readonly IMonarchDbContext m_db;
public DatabaseBackup(IMonarchDbContext podb)
{
if (podb == null)
throw new ArgumentNullException("podb");
m_db = podb;
}
public DBBackupHistory GetLatestBackupHistory(DBBackupFrequency backupFrequency = DBBackupFrequency.Periodic)
{
DBBackupHistory result = null;
// get the backup history of the given backuptype and populate the objects
var configId = m_db.DBBackupConfigurations.Where(c => c.ScheduleType == (int)backupFrequency && c.BackupStatus == 1).Distinct().Select(c => c.ConfigurationId).DefaultIfEmpty(-1).First();
if (configId > 0)
{
result = m_db.DBBackupHistorys.Where(b => b.Status == 1 && b.ConfigurationId == configId).OrderByDescending(lb => lb.BackupDatetime).FirstOrDefault();
}
return result;
}
public IEnumerable<DBBackupConfiguration> GetAllConfiguration()
{
var result = m_db.DBBackupConfigurations.Where(c => c.BackupStatus == 1).OrderByDescending(c => c.ConfigurationId);
return result;
}
public void Backup(DBBackupConfiguration config, int fileIndex)
{
Console.WriteLine("Running DB Backup type {0} to device {1}", (DBBackupType)config.BackupType, fileIndex);
m_db.StoredProc.SPBackup(config, fileIndex);
}
I am calling the below methods in another class as follows
private readonly IDataBackup m_dataBackup;
public int PerformBackup(int defaultPollIntervalInMinutes = 15)
{
// polling interval in Minutes
int pollInterval = defaultPollIntervalInMinutes;
int fileIndex = getCurrentDumpFileIndex();
// check for the backup configuration
var configurations = m_dataBackup.GetAllConfiguration();
foreach (var config in configurations)
{
var lastBackup = m_dataBackup.GetLatestBackupHistory(DBBackupFrequency.Weekly);
if (lastBackup == null)
{
m_dataBackup.Backup(config, fileIndex + 1);
break;
}
Here is the Db Context class is as below
public class MonarchDbContext:DbContext,IMonarchDbContext
{
private IStoredProcedure m_storedProc;
private static object m_dbIntializerSet;
public MonarchDbContext(string nameOrConnectionString)
: base( nameOrConnectionString )
{
//-- Set the DB initializer only once.
System.Threading.LazyInitializer.EnsureInitialized( ref m_dbIntializerSet,()=>{
Database.SetInitializer<MonarchDbContext>(null);
//-- Give debug builds a chance to overwrite the above.
_SetInitializerForDebugBuilds();
return new object();
});
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
var csb = new SqlConnectionStringBuilder( this.Database.Connection.ConnectionString );
csb.MultipleActiveResultSets = true;
this.Database.Connection.ConnectionString = csb.ToString();
var objectContext = ( this as IObjectContextAdapter ).ObjectContext;
objectContext.CommandTimeout = 3600;
}
#region Public "Tables"
public IDbSet<DBBackupConfiguration> DBBackupConfigurations { get; set; }
public IDbSet<DBBackupHistory> DBBackupHistorys { get; set; }
public IStoredProcedure StoredProc
{
get
{
return System.Threading.LazyInitializer.EnsureInitialized(ref m_storedProc, () => new BackupStoredProc(this.Database));
}
}
#endregion
please let me know how can i solve the issue.
I found the issue
I need to add toList() at the end of the Linq code and it just worked for me.
public IEnumerable<DBBackupConfiguration> GetAllConfiguration()
{
var result = m_db.DBBackupConfigurations.Where(c => c.BackupStatus == 1).OrderByDescending(c => c.ConfigurationId).ToList();
return result;
}
Just add the List to Ienumerbale types

Categories