I am overriding SaveChangesAsync to handle DbUpdateConcurrencyException. For example:
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
var saved = false;
var loopCount = 0;
var count = 0;
while (!saved && ++loopCount < 4)
{
try
{
count = await base.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
saved = true;
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
entry.OriginalValues.SetValues(entry.CurrentValues);
}
}
}
return count;
}
My question is: how do I force the base class (DbContext) to throw a DbUpdateConcurrencyException in a test?
Note: Please don't suggest wrapping or other abstractions as those are certainly overkill in this case.
I have refactored a Web API to rely on async/await in ASP.NET Core 3.1 and I have the following scenario: a statistics method is sequentially computing a list of indicators which are defined in a list.
readonly Dictionary<StatisticItemEnum, Func<Task<SimpleStatisticItemApiModel>>> simpleItemActionMap =
new Dictionary<StatisticItemEnum, Func<Task<SimpleStatisticItemApiModel>>>();
private void InitSimpleStatisticFunctionsMap()
{
simpleItemActionMap.Add(StatisticItemEnum.AllQuestionCount, GetAllQuestionCountApiModel);
simpleItemActionMap.Add(StatisticItemEnum.AllAnswerCount, GetAllAnswerCountApiModel);
simpleItemActionMap.Add(StatisticItemEnum.AverageAnswer, GetAverageAnswer);
// other mappings here
}
private async Task<SimpleStatisticItemApiModel> GetAllQuestionCountApiModel()
{
// await for database operation
}
private async Task<SimpleStatisticItemApiModel> GetAllAnswerCountApiModel()
{
// await for database operation
}
private async Task<SimpleStatisticItemApiModel> GetAverageAnswer()
{
// await for database operation
}
The code sequentially goes through each item and computes it and after the refactoring it is looking like this:
itemIds.ForEach(itemId =>
{
var itemEnumValue = (StatisticItemEnum) itemId;
if (simpleItemActionMap.ContainsKey(itemEnumValue))
{
var result = simpleItemActionMap[itemEnumValue]().Result;
payload.SimpleStatisticItemModels.Add(result);
}
});
I know that Task.Result might lead to deadlocks, but I could not find any other way to make this work.
Question: How to execute a dynamic list of async functions in a sequential way?
You should change the ForEach call to a regular foreach, and then you can use await:
foreach (var itemId in itemIds)
{
var itemEnumValue = (StatisticItemEnum) itemId;
if (simpleItemActionMap.ContainsKey(itemEnumValue))
{
var result = await simpleItemActionMap[itemEnumValue]();
payload.SimpleStatisticItemModels.Add(result);
}
}
Do not make the ForEach lambda async; that will result in an async void method, and you should avoid async void.
I think you can do this:
itemIds.ForEach(async itemId =>
{
var itemEnumValue = (StatisticItemEnum) itemId;
if (simpleItemActionMap.ContainsKey(itemEnumValue))
{
var result = await simpleItemActionMap[itemEnumValue]();
payload.SimpleStatisticItemModels.Add(result);
}
});
I want to automate the Setup code by a given array containing expected result and parameters.
Something like data driven setup.
My existing code:
var mock = new Mock<ILogin>();
var testDataTable = new object[,]
{
{ LoginResult.Success, "Jack", "123!##"}
, { LoginResult.WrongPassword, "Jack", "123321"}
, { LoginResult.NoSuchUser, "Peter", "123!##"}
};
// ForEachRow is my own extension method
testDataTable.ForEachRow((row) =>
{
var result = (LoginResult)row[0];
var username = (string)row[1];
var password = (string)row[2];
mock.Setup(o => o.Login(
It.Is<string>(u => u == username),
It.Is<string>(p => p == password)
)).Returns(result);
});
return mock.Object;
Code that I wish:
var mock = new Mock<ILogin>();
new object[,]
{
{ LoginResult.Success, "Jack", "123!##"}
, { LoginResult.WrongPassword, "Jack", "123321"}
, { LoginResult.NoSuchUser, "Peter", "123!##"}
}.ForEachRow((row) =>
{
var exprTree = (ILogin o)=>o.Login("ANY", "ANY");
AutoSetup(mock, exprTree, row); // <---- How to write this AutoSetup?
});
return mock.Object;
How to write the AutoSetup(mock, exprTree, dataArray) function above?
It takes three parameters:
mock: A mock object, e.g. new Mock()
exprTree: Expression tree that represents a method to be setup
dataArray: An object[], the 0 element is the expected result, and others are parameters that passed to the method
This was an interesting challenge. I think I have a working implementation for your AutoSetup method, using the expressions API. If anyone has a simpler solution, I'd love to see it.
static void AutoSetup<TMock, TResult>(Mock<TMock> mock, Expression<Func<TMock, TResult>> exprTree, object[] items) where TMock : class
{
var methodCallExpr = exprTree.Body as MethodCallExpression;
var arguments = items.Skip(1).Select(o => Expression.Constant(o));
var updatedMethod = methodCallExpr.Update(methodCallExpr.Object, arguments);
var updatedLambda = exprTree.Update(updatedMethod, exprTree.Parameters);
mock.Setup(updatedLambda).Returns((TResult)items[0]);
}
Here is a full working test as a console app, with an implementation of ForEachRow, which you didn't provide.
class Program
{
static void Main(string[] args)
{
var login = SetUp();
Console.WriteLine(login.Login("Jack", "123!##"));
Console.WriteLine(login.Login("Jack", "123321"));
Console.WriteLine(login.Login("Peter", "123!##"));
Console.ReadKey();
}
static ILogin SetUp()
{
var mock = new Mock<ILogin>(MockBehavior.Strict);
var rows = new object[,]
{
{ LoginResult.Success, "Jack", "123!##" },
{ LoginResult.WrongPassword, "Jack", "123321" },
{ LoginResult.NoSuchUser, "Peter", "123!##" }
};
rows.ForEachRow((row) => AutoSetup(mock, (ILogin l) => l.Login("ANY", "ANY"), row));
return mock.Object;
}
private static void AutoSetup<TMock, TResult>(Mock<TMock> mock, Expression<Func<TMock, TResult>> exprTree, object[] items) where TMock : class
{
var methodCallExpr = exprTree.Body as MethodCallExpression;
var arguments = items.Skip(1).Select(o => Expression.Constant(o));
var updatedMethod = methodCallExpr.Update(methodCallExpr.Object, arguments);
var updatedLambda = exprTree.Update(updatedMethod, exprTree.Parameters);
mock.Setup(updatedLambda).Returns((TResult)items[0]);
}
}
public static class ArrayExtensions
{
public static void ForEachRow<T>(this T[,] rows, Action<T[]> action)
{
var x = rows.GetLength(1);
var y = rows.GetLength(0);
for (int i = 0; i < y; i++)
{
var row = new T[x];
for (int j = 0; j < x; j++)
{
row[j] = rows[i, j];
}
action(row);
}
}
}
public interface ILogin
{
LoginResult Login(string p1, string p2);
}
public enum LoginResult
{
Success,
WrongPassword,
NoSuchUser
}
EDIT: You asked in a comment about how to take advantage of the variable parameter matching that Moq provides with the It.IsAny<> method. Because what you pass to your Mock.Setup() is an expression tree, it's able to scan the method parameters and implement special behaviour for any that are calls to It.IsAny<>. However, if you use It.IsAny<> in your test data array, by the time we retrieve it from your items array to set in on the expression, it's not a method call but simply the result of the call it It.IsAny<> which is default(T) (see here).
We need some way of specifying in your test data array that the parameter should be any. Then we can check for this special case and generate the correct MethodCallExpression representing a call to It.IsAny<>.
Here are the changes I made to support this:
Add an Any type to use in your test data
public class Any<T>
{
private Any() { }
public static Any<T> Param { get { return new Any<T>(); } }
}
Update the AutoSetup method to handle this special case:
private static void AutoSetup<TMock, TResult>(Mock<TMock> mock, Expression<Func<TMock, TResult>> exprTree, object[] items) where TMock : class
{
var arguments = items.Skip(1).Select(o => {
var type = o.GetType();
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Any<>))
{
var typeParameter = type.GetGenericArguments();
var genericItIsAny = typeof(It).GetMethod("IsAny");
var itIsAny = genericItIsAny.MakeGenericMethod(typeParameter);
return Expression.Call(itIsAny) as Expression;
}
return Expression.Constant(o);
});
var methodCallExpr = exprTree.Body as MethodCallExpression;
var updatedMethod = methodCallExpr.Update(methodCallExpr.Object, arguments);
var updatedLambda = exprTree.Update(updatedMethod, exprTree.Parameters);
mock.Setup(updatedLambda).Returns((TResult)items[0]);
}
In the test data, use the Any type
{ LoginResult.Success, "NoPasswordUser", Any<string>.Param }
Depending on how you're storing your test data, you might need another way of identifying parameters that you want to be variable (specially formatted string?), but in general this should give you an idea about how to create the correct expressions.
I'm trying to figure out how to add text to the bottom of a list box and display it. In WPF with code behind, I would grab the ScrollViewer and manipulate it, but I can't figure out how to do it with Caliburn...
You have a couple options.
1) In your ViewModel you can call GetView and cast it to your view type and get a reference to the ScrollViewer. Something like:
var myView = this.GetView() as MyView;
var myScrollView = myView.MyScrollView;
That works fine but isn't ideal if you're trying to not couple the view to the view model.
Option 2) is to implement IResult, see docs here.
public class ScrollViewResult : IResult
{
public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };
private ScrollViewResult ()
{
}
public void Execute (ActionExecutionContext context)
{
var view = context.View as FrameworkElement;
var scrollViewer = FindVisualChild<ScrollViewer>(view);
//do stuff to scrollViewer here
Completed (this, new ResultCompletionEventArgs { });
}
private static TChildItem FindVisualChild<TChildItem> (DependencyObject obj)
where TChildItem : DependencyObject
{
for (var i = 0; i < VisualTreeHelper.GetChildrenCount (obj); i++)
{
var child = VisualTreeHelper.GetChild (obj, i);
if (child != null && child is TChildItem)
return (TChildItem)child;
var childOfChild = FindVisualChild<TChildItem> (child);
if (childOfChild != null)
return childOfChild;
}
return null;
}
//this isn't required of course but comes in handy for
//having a static method and passing parameters to the
//ctor of the IResult
public static IResult DoSomething ()
{
return new ScrollViewResult ();
}
Then you can call it like:
public IEnumerable<IResult> SomeAction()
{
yield return ScrollViewResult.DoSomething();
}
I am writing a Metro App.
I am trying to read a file and return a float[] from the data. But no matter what I do, the function seems to return null. I have tried the solutions to similar questions to no luck.
For example if I use:
float[] floatArray = new ModelReader("filename.txt").ReadModel()
The result will be a null array.
However if I use:
new ModelReader("filename.txt")
The correct array will be printed to the console because "Test" also prints the array before returning it. This seems very weird to me.
Please give me some guidance, I have no idea what is wrong.
public class ModelReader
{
float[] array;
public ModelReader(String name)
{
ReadModelAsync(name);
}
public float[] ReadModel()
{
return array;
}
private async Task ReadModelAsync(String name)
{
await readFile(name);
}
async Task readFile(String name)
{
// settings
var path = #"Assets\models\" + name;
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
// acquire file
var file = await folder.GetFileAsync(path);
// read content
var read = await Windows.Storage.FileIO.ReadTextAsync(file);
using (StringReader sr = new StringReader(read))
{
Test test = new Test(getFloatArray(sr));
this.array = test.printArray();
}
}
private float[] getFloatArray(StringReader sr) { ... }
public class Test
{
public float[] floatArray;
public Test(float[] floatArray)
{
this.floatArray = floatArray;
}
public float[] printArray()
{
for (int i = 0; i < floatArray.Length; i++)
{
Debug.WriteLine(floatArray[i]);
}
return floatArray;
}
}
You're trying to get the result of an asynchronous operation before it has completed. I recommend you read my intro to async / await and follow-up with the async / await FAQ.
In particular, your constructor:
public ModelReader(String name)
{
ReadModelAsync(name);
}
is returning before ReadModelAsync is complete. Since constructors cannot be asynchronous, I recommend you use an asynchronous factory or asynchronous lazy initialization as described on my blog (also available in my AsyncEx library).
Here's a simple example using an asynchronous factory approach:
public class ModelReader
{
float[] array;
private ModelReader()
{
}
public static async Task<ModelReader> Create(string name)
{
var ret = new ModelReader();
await ret.ReadModelAsync(name);
return ret;
}
...
}