The source IQueryable doesn't implement IDbAsyncEnumerable when trying to mock - c#

I am trying to test a bit of code I have:
public async Task<Sortation> SaveAsync(Sortation sortation)
{
if (sortation.Id == 0)
{
var sortations = await ListAsync(sortation.CategoryId);
sortation.Order = sortations.Count;
_sortationService.Create(sortation);
}
else
{
_sortationService.Update(sortation);
}
await _sortationService.SaveChangesAsync();
return sortation;
}
The ListAsync method is causing me an issue.
I set up my test like this:
[Test]
public async Task ShouldHaveOrderOfZero()
{
// Assemble
const string categoryId = "cameras";
var services = SortationContext.GivenServices();
var sortationProvider = services.WhenGetSortationProvider();
var sortations = new List<Sortation>();
var sortation = new Sortation { CategoryId = categoryId };
services.MockSortationService.Setup(x => x.List()).Returns(sortations.AsQueryable);
// Act
await sortationProvider.SaveAsync(sortation);
// Assert
sortation.Order.Should().Be(0);
}
And when I run this, I get this error:
Message: System.InvalidOperationException : The source IQueryable doesn't implement IDbAsyncEnumerable. Only sources that implement IDbAsyncEnumerable can be used for Entity Framework asynchronous operations.
According to this: Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations I need to add EF to my UnitTest project, which I did.
But the error still persists.
The ListAsync method looks like this:
public async Task<List<Sortation>> ListAsync(string categoryId, params string[] includes) =>
await _sortationService.List(includes).Where(m => m.CategoryId.Equals(categoryId)).ToListAsync();
Does anyone know how I can stop this error from happening?

In my case the exception was caused by using the wrong ToListAsync extension.
It came from:
using System.Data.Entity;
instead of
using Microsoft.EntityFrameworkCore;
Changing the namespace fixed the error.

Don't know if question is still actual, but still. I agree with Mark's comment, however here is an example, that works for me. I added some reasonable stub implementation for mentioned class, because there are not enouch details in question. I can be wrong in my assumptions:
[Test]
public async Task ShouldHaveOrderOfZero()
{
// Assemble
const string categoryId = "cameras";
var services = SortationContext.GivenServices();
var sortationProvider = services.WhenGetSortationProvider();
var sortations = new List<Sortation>();
var sortation = new Sortation { CategoryId = categoryId };
// the key moq configuration here
services.MockSortationService.Setup(x => x.ListAsync(It.IsAny<string>())).Returns(Task.FromResult(sortations));
// Act
await sortationProvider.SaveAsync(sortation);
// Assert
sortation.Order.Should().Be(0);
}
public class SortationProvider
{
private SortationService _sortationService;
public SortationProvider()
{
_sortationService = new SortationService();
}
public async Task<Sortation> SaveAsync(Sortation sortation)
{
if (sortation.Id == 0)
{
var sortations = await ListAsync(sortation.CategoryId);
sortation.Order = sortations.Count;
_sortationService.Create(sortation);
}
else
{
_sortationService.Update(sortation);
}
await _sortationService.SaveChangesAsync();
return sortation;
}
// should be virtual
public virtual async Task<List<Sortation>> ListAsync(string categoryId, params string[] includes) =>
await _sortationService.List(includes).Where(m => m.CategoryId.Equals(categoryId)).ToListAsync();
}
public class SortationContext
{
public static Services GivenServices()
{
return new Services();
}
}
public class Services
{
public Services()
{
MockSortationService = new Mock<SortationProvider>();
}
public SortationProvider WhenGetSortationProvider()
{
return MockSortationService.Object;
}
public Mock<SortationProvider> MockSortationService { get; set; }
}
internal class SortationService
{
public void Create(Sortation sortation)
{
}
public void Update(Sortation sortation)
{
}
public Task SaveChangesAsync()
{
return Task.CompletedTask;
}
public DbSet<Sortation> List(string[] includes)
{
throw new NotImplementedException();
}
}
public class Sortation
{
public string CategoryId { get; set; }
public int Id { get; set; }
public int Order { get; set; }
}
The main change is in line that contains Setup method. I made ListAsync method virtual also. The main assumption is that List(string[] includes) method returns DbSet<Sortation>. Hope it helps.

Related

NSubstitute and DbContext.Set<TEntity> Could not find a call to return from

I am trying to write some tests for an existing service we have. It uses the DbContext (In our case, named DatabaseContext) and the constructor looks like this:
public GenericOrderProvider(DatabaseContext context, IOrderHandler<T> orderHandler)
{
_orderHandler = orderHandler;
_context = context;
_dbSet = context.Set<T>();
}
As you can see, it's generic and sets the _dbSet when it's initialized.
I have this very simple method:
public Attempt<IQueryable<T>> List(params string[] includes)
{
var x = _dbSet.ToList();
return Attempt<IQueryable<T>>.Succeed(_dbSet.OrderBy(m => m.Order));
}
And I wrote this test:
[TestFixture]
public class ListShould
{
[Test]
public void ReturnList()
{
// Assemble
var services = GenericOrderProviderContext.GivenServices();
var provider = services.WhenCreateOrderProvider();
services.DatabaseContext.Set<Attribute>().ReturnsForAnyArgs(new List<Attribute>().ToDbSet());
//services.DatabaseContext.Attributes = new List<Attribute>().ToDbSet();
// Act
var result = provider.List();
// Assert
result.Failure.Should().BeFalse();
result.Result.Count().Should().Be(0);
}
}
When I run that test, I get the error:
NSubstitute.Exceptions.CouldNotSetReturnDueToNoLastCallException : Could not find a call to return from.
The trace specifically targets the line services.DatabaseContext.Set<Attribute>().ReturnsForAnyArgs(new List<Attribute>().ToDbSet()); but I have no idea how to fix it.
As far as I can tell, I am mapping to the right method.
For completeness, here is my test Contexts:
public class GenericOrderProviderContext: DatabaseContextContext<GenericOrderProviderContext>
{
public static GenericOrderProviderContext GivenServices() => new GenericOrderProviderContext();
public IGenericOrderProvider<Attribute> WhenCreateOrderProvider() =>
new GenericOrderProvider<Attribute>(DatabaseContext,
new OrderHandler<Attribute>(DatabaseContext));
public bool IsSequential(List<Attribute> models)
{
return !models.OrderBy(m => m.Order).Select(m => m.Order).Select((i, j) => i - j).Distinct().Skip(1).Any();
}
}
public class DatabaseContextContext<T> where T: DatabaseContextContext<T>
{
public DatabaseContext DatabaseContext;
protected DatabaseContextContext()
{
DatabaseContext = Substitute.For<DatabaseContext>();
}
}
Does anyone know what I can do to resolve this issue?

Xamarin sqlite-net-pcl accessing values of database internal

I'm using Visual Studio 2017, new to SQLite and can't get my head behind how I get to access the values saved in the database and get it back to the elements of the class.
public class MyObject
{
[PrimaryKey, AutoIncrement]
public int IndexNumber
{get;set;}
[MaxLength(20)]
public int SomeID
{get;set;}
[MaxLength(70)]
public string SomeName
{get; set;}
[MaxLength(25)]
public string Telephone
{get; set;}
public DateTime someTime
{get; set;}
//...some more data
}
public class MyDB
{
readonly SQLiteAsyncConnection database;
public MyDB (string dbPath);
database.CreateTableAsync<MyObject>().Wait();
public Task<List<MyObject>> GetMyObjectAsync()
{
return database.Table<MyObject>().ToListAsync();
}
public Task<MyObject> GetSingleObjectAsync(int ind)
{
return database.Table<MyObject>().Where(i => i.IndexNumber == ind).FirstOrDefaultAsync();
}
public Task<int> SaveMyObjectAsync(MyObject object)
{
if (object.IndexNumber == 0)
{
return database.InsertAsync(object)
}
else
{
return database.UpdateAsync(object);
}
}
public Task<int> DeleteMyObjectAsync(MyObject object)
{
return database.DeleteAsync(object);
}
}
Inputting data through the .xaml pages works without any problems so far, selecting the object in ListView works as well.
The problem now is that I just can't seem to find a proper way to convert the returned Task back to an object to update some of those values with data only supplied through a HTTP response which itself does not always supply all the data for the datatable, e.g. only the ID and a code if it was successful in the first response.
It then needs other data from the object and again delivers values for different elements of the object which is why I'd like to know if there was some method to get a row of data back to a temporary object to update it in the database, remove it if needed (canceled through the HTTP response) or modify it.
Your problem is all about not using await keyword. Whenever you call asynchronous method with no await keyword you are doing it wrong :) I strongly recommend you to read James Montemagno blog post about it here.
Here is solution of your problems.
public class MyDB
{
readonly SQLiteAsyncConnection database;
public MyDB(string dbPath)
{
database = new SQLiteAsyncConnection(dbPath);
}
public async Task CreteMyDb()
{
await database.CreateTableAsync<MyObject>();
}
public async Task<List<MyObject>> GetMyObjectsAsync()
{
return await database.Table<MyObject>().ToListAsync();
}
public async Task<MyObject> GetSingleObjectAsync(int ind)
{
return await database.Table<MyObject>().Where(i => i.IndexNumber == ind).FirstOrDefaultAsync();
}
public async Task<int> SaveMyObjectAsync(MyObject myObject)
{
if (myObject.IndexNumber == 0)
{
return await database.InsertAsync(myObject);
}
else
{
return await database.UpdateAsync(myObject);
}
}
public async Task<int> DeleteMyObjectAsync(MyObject myObject)
{
return await database.DeleteAsync(myObject);
}
}
And example usage of methods.
await this.myDb.CreteMyDb();
await this.myDb.SaveMyObjectAsync(new MyObject()
{
SomeID = 1,
SomeName = "Adam",
someTime = DateTime.Now,
Telephone = "53535353"
});
var list = await this.myDb.GetMyObjectAsync();
Let me know if it helped!

How to make a custom attribute in C# for mapping intents in Microsoft Bot Framework?

The [LuisIntent("")] attribute uses the ILuisService to query
the LUIS based on LUISModel attributes' value, then finds out the
top scoring intent and matches the IntentHandler Delegate in the
overridden MessageRecievedAsync method and loads the
LUISResult dynamically in the following method while debugging a class which inherits from LuisDialog.
public async Task None(IDialogContext context, LuisResult result)
{
//some stuff
}
My question is how to make a custom attribute which maps it to the correct intent handler.
I am trying to use RASA NLU Service as my NLP engine along with Microsoft Bot Framework in C#.
I am trying to map LUISEmulatedResult which I get from HttpClient.GetAsync() method which queries RASA NLU to get LUISResult type JSON to a method which follows this delegate.
Progress I have done:
The [RASAIntentAttribute("IntentName")]
using Microsoft.Bot.Builder.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
namespace DemoFlightRASA.Models
{
public class RASAIntentAttribute : Attribute
{
private readonly string _intentName;
public RASAIntentAttribute(string IntentName)
{
this._intentName = IntentName;
}
//The intent handler delegate
//Now I want to map LUISEmulatedResult which I get from HttpClient.GetAsync() method to a method which follows this delegate
public delegate Task RASAIntentHandler(IDialogContext context, LUISEmulatedResult result);
}
}
The LUISEmulatedResult model class:
namespace DemoFlightRASA.Models
{
public class LUISEmulatedResult
{
public string query { get; set; }
public Topscoringintent topScoringIntent { get; set; }
public Intent[] intents { get; set; }
public Entity[] entities { get; set; }
}
public class Topscoringintent
{
public string intent { get; set; }
public float score { get; set; }
}
public class Intent
{
public string intent { get; set; }
public float score { get; set; }
}
public class Entity
{
public string entity { get; set; }
public string type { get; set; }
public int startIndex { get; set; }
public int endIndex { get; set; }
public Resolution resolution { get; set; }
public float score { get; set; }
}
public class Resolution
{
public string[] values { get; set; }
}
}
Also I tried this one, but this doesn't seem to work
I want to create a end-to-end flow which uses RASA NLU opposed to LUIS in bot framework. I have the RASA NLU endpoint ready, just not able to make the RASAIntentAttribute.
Any pointers, tips, tutorials, code snippets as to how to map the delegate to the method will be greatly appreciated. Thank you.
Note: I don't think you can have a delegate as an attribute parameter: Is it possible to have a delegate as attribute parameter? How are you planning to use the RASAIntentHandler delegate?
The .net Bot Framework sdk uses reflection to determine which methods in the LuisDialog are intent handlers: https://github.com/Microsoft/BotBuilder/blob/b6cd3ff85e8dc57ac586a11db489a0c75c635ae2/CSharp/Library/Microsoft.Bot.Builder/Dialogs/LuisDialog.cs#L362
public static IEnumerable<KeyValuePair<string, IntentActivityHandler>> EnumerateHandlers(object dialog)
{
var type = dialog.GetType();
var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (var method in methods)
{
var intents = method.GetCustomAttributes<LuisIntentAttribute>(inherit: true).ToArray();
IntentActivityHandler intentHandler = null;
try
{
intentHandler = (IntentActivityHandler)Delegate.CreateDelegate(typeof(IntentActivityHandler), dialog, method, throwOnBindFailure: false);
}
catch (ArgumentException)
{
// "Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type."
// https://github.com/Microsoft/BotBuilder/issues/634
// https://github.com/Microsoft/BotBuilder/issues/435
}
// fall back for compatibility
if (intentHandler == null)
{
try
{
var handler = (IntentHandler)Delegate.CreateDelegate(typeof(IntentHandler), dialog, method, throwOnBindFailure: false);
if (handler != null)
{
// thunk from new to old delegate type
intentHandler = (context, message, result) => handler(context, result);
}
}
catch (ArgumentException)
{
// "Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type."
// https://github.com/Microsoft/BotBuilder/issues/634
// https://github.com/Microsoft/BotBuilder/issues/435
}
}
if (intentHandler != null)
{
var intentNames = intents.Select(i => i.IntentName).DefaultIfEmpty(method.Name);
foreach (var intentName in intentNames)
{
var key = string.IsNullOrWhiteSpace(intentName) ? string.Empty : intentName;
yield return new KeyValuePair<string, IntentActivityHandler>(intentName, intentHandler);
}
}
else
{
if (intents.Length > 0)
{
throw new InvalidIntentHandlerException(string.Join(";", intents.Select(i => i.IntentName)), method);
}
}
}
}
Here is the code in LuisDialog that calls the handler that corresponds to the best intent in the IntentRecommendation returned from LUISs: https://github.com/Microsoft/BotBuilder/blob/b6cd3ff85e8dc57ac586a11db489a0c75c635ae2/CSharp/Library/Microsoft.Bot.Builder/Dialogs/LuisDialog.cs#L252
protected virtual async Task DispatchToIntentHandler(IDialogContext context,
IAwaitable<IMessageActivity> item,
IntentRecommendation bestIntent,
LuisResult result)
{
if (this.handlerByIntent == null)
{
this.handlerByIntent = new Dictionary<string, IntentActivityHandler>(GetHandlersByIntent());
}
IntentActivityHandler handler = null;
if (result == null || !this.handlerByIntent.TryGetValue(bestIntent.Intent, out handler))
{
handler = this.handlerByIntent[string.Empty];
}
if (handler != null)
{
await handler(context, item, result);
}
else
{
var text = $"No default intent handler found.";
throw new Exception(text);
}
}
This is how LUIS results are mapped to methods marked with the LUISIntentAttribute on LUISDialogs. This functionality, or something similar, will need to be in the RASA implementation.

Moq Verify with anonymous type parameter

I have the following test, with supporting classes, but I can't figure out how to verify the call on the dependency.
[TestFixture]
public class AnonymousGenericTypeParameterTests
{
[Test]
public void Test()
{
// Arrange
var dependency = new Mock<IDependency>();
var towns = new List<Town>
{
new Town { Name = "Lifford", County = "Donegal", Country="Ireland", Population = 1658 },
new Town { Name = "Ballyshannon", County = "Donegal", Country="Ireland", Population = 2504 },
new Town { Name = "Buxton", County = "Derbyshire", Country="United Kingdom", Population = 13599 },
};
var sut = new MyClass(dependency.Object);
// Act
sut.DoSomething(towns);
// Assert
// The following line needs to be fixed.
dependency.Verify(d => d.Execute(It.IsAny<IEnumerable<object>>(), It.IsAny<Func<object, decimal?>>()));
}
}
public interface IDependency
{
void Execute<T>(IEnumerable<T> collection, Func<T, decimal?> rateSelector);
}
public class MyClass
{
private readonly IDependency dependency;
public MyClass(IDependency dependency)
{
this.dependency = dependency;
}
public void DoSomething(IEnumerable<Town> towns)
{
var counties = towns.GroupBy(t => new {t.Country,t.County});
foreach (var county in counties)
{
dependency.Execute(county, c => c.Population);
}
}
}
public class Town
{
public string Name { get; set; }
public string County { get; set; }
public int Population { get; set; }
public string Country { get; set; }
}
According to Moq's test output, the performed invocations are:
Dependency.Execute(System.Linq.Lookup`2+Grouping[<>f__AnonymousType0`2[System.String,System.String],UniFocus.Staffscope4.Tests.Town], System.Func`2[UniFocus.Staffscope4.Tests.Town,System.Nullable`1[System.Decimal]])
I see plenty of questions regarding anonymous parameters in Moq (such as this and this and this), but can't find anything relating to using an anonymous type as the actual type parameter.
What can be put in the Verify line so that it actually verifies the call inside?
Note: My example IDependency doesn't return a value (it's already complex enough, I think), but there will be bonus kudos for answers that implictly or explicitly address Setup() as well as Verify().
Update
Jesse's solution only passes the test because I made a bad choice when crafting my example. I should have realised that any IGrouping<out TKey, out TElement> is also an IEnumerable<TElement>. Is there a more universal solution?
Update 2
I feel like my original example was possibly too elaborate and didn't represent well the actual title of my question. Is there any solution that works for this more straightforward and to-the-point example?
using Moq;
using NUnit.Framework;
namespace Tests
{
[TestFixture]
public class SimpleAnonymousGenericTypeParameterTests
{
[Test]
public void Test()
{
// Arrange
var dependency = new Mock<IDependency>();
var sut = new MyClass(dependency.Object);
// Act
sut.DoSomething("Donegal", "Lifford");
// Assert
// This verify works for both calls to Execute()
dependency.Verify(d => d.Execute(It.IsAny<object>()), Times.Exactly(2));
// This verify should specifically refer to only the first call to Execute()
dependency.Verify(d => d.Execute(It.IsAny</*HowToRepresentAnonymousTypeHere*/object>()), Times.Once);
}
public interface IDependency
{
void Execute<T>(T thing);
}
public class MyClass
{
private readonly IDependency dependency;
public MyClass(IDependency dependency)
{
this.dependency = dependency;
}
public void DoSomething(string county, string town)
{
dependency.Execute(new { county, town });
object someUnknownObject = "";
dependency.Execute(someUnknownObject);
}
}
}
}
The accepted answer doesn't work for me, I believe it's because the tests and the object in question are in a different assembly so Moq doesn't know how to reconcile the types and does not match them.
Instead, I created the following helper methods that can verify that the anonymous type provided has the correct fields and values:
public static class AnonHelpers
{
public static object MatchAnonymousType(object expected)
{
return Match.Create(Matcher(expected));
}
private static Predicate<object> Matcher(object expected)
{
return actual =>
{
var expectedProp = expected.GetType().GetProperties().ToDictionary(x => x.Name, x => x.GetValue(expected));
var actualProp = actual.GetType().GetProperties().ToDictionary(x => x.Name, x => x.GetValue(actual));
foreach (var prop in expectedProp)
{
if (!actualProp.ContainsKey(prop.Key))
return false;
if (!prop.Value.Equals(actualProp[prop.Key]))
return false;
}
return true;
};
}
}
They can be used like so:
var anon = new { SomeKey = "some value", SomeOtherKey = 123 };
myMock.Setup(x => x.MyMethod(personIDs, AnonHelpers.MatchAnonymousType(anon))).Verifiable();
This will create a matcher that will use reflection to match the anonymous type based on it's keys and values and then you can use normal verification to see when it's been called.
Since the types are known in the context of the test, you could provide the specific type arguments to the Verify call. The following change got the test to pass:
dependency.Verify(d =>
d.Execute(It.IsAny<IEnumerable<Town>>(), It.IsAny<Func<Town, decimal?>>()));
The same should also work for setups.
With regards to the example in Update 2, the following passes, but it requires knowledge of the inner workings of the DoSomething() method and as far as I know it's the only way to make it work:
var anonymousType = new {county = "Donegal", town = "Lifford"};
dependency.Verify(d => d.Execute(anonymousType), Times.Once);

How to Implement Repository FindAll() Method?

I have the following Repository Pattern. Requirement is to “Find All accounts whose owner’s name is Lijo”. So, I need to write a FindAll function. How to write this function?
Constraints are:
1) The client “BankAccountService” should not use classes from 'DBML_Project'.
2) We should NOT use GetAll method to retireve complete list of accounts and then do a filter.
Note: I confronted this problem while working on the question Polymorphism: Is ORM entity a Domain Entity or Data Entity?
CODE
namespace ApplicationService_Bank
{
public class BankAccountService
{
RepositoryLayer.ILijosBankRepository accountRepository = new RepositoryLayer.LijosSimpleBankRepository();
public void FreezeAllAccountsForUser(string userName)
{
//Should not use assembly 'DBML_Project'.
IEnumerable<DomainEntitiesForBank.IBankAccount> accountsForUserWithNameLIJO = null;
//accountsForUserWithNameLIJO = accountRepository.FindAll(p => p.BankUser.Name == "Lijo");
}
}
}
namespace RepositoryLayer
{
public interface ILijosBankRepository
{
List<DomainEntitiesForBank.IBankAccount> GetAll();
IEnumerable<DBML_Project.BankAccount> FindAll(System.Func<DBML_Project.BankAccount, bool> predicate);
void SubmitChanges();
}
public class LijosSimpleBankRepository : ILijosBankRepository
{
private IBankAccountFactory bankFactory = new MySimpleBankAccountFactory();
public System.Data.Linq.DataContext Context
{
get;
set;
}
public virtual List<DomainEntitiesForBank.IBankAccount> GetAll()
{
List<DBML_Project.BankAccount> allItems = Context.GetTable<DBML_Project.BankAccount>().ToList();
List<DomainEntitiesForBank.IBankAccount> bankAccounts = new List<DomainEntitiesForBank.IBankAccount>();
foreach (DBML_Project.BankAccount acc in allItems)
{
DomainEntitiesForBank.IBankAccount theAccount = bankFactory.CreateAccount(acc.AccountType, acc.BankAccountID, acc.Status, acc.OpenedDate, acc.AccountOwnerID);
bankAccounts.Add(theAccount);
}
return bankAccounts;
}
public IEnumerable<DBML_Project.BankAccount> FindAll(System.Func<DBML_Project.BankAccount, bool> predicate)
{
//Where
var results = Context.GetTable<DBML_Project.BankAccount>().Where(predicate);
return results;
}
public virtual void SubmitChanges()
{
Context.SubmitChanges();
}
}
}
READING:
Returning IEnumerable<T> vs. IQueryable<T>
how to design Repository pattern to be easy switch to another ORM later?
A simple approach is to just build the query by hand:
public class SearchCriteria
{
public string Name { get; set; }
// ...more
}
public IEnumerable<Entity> FindAll(SearchCriteria criteria)
{
IQueryable<Entity> entities = _datasource.Entities; // replace with your L2S equivalent
if (criteria.Name != null)
entities = entities.Where(e => e.Name == criteria.Name);
// ...more
return entities;
}
If you don't want to return the generated objects directly, map to something else before you return:
return Map(entities); // IEnumerable<CustomObject> Map(IEnumerable<Entity> entities)

Categories