ASP.NET Core 7 WebApplicationFactory Integration tests. How to load data? - asp.net-core

I am creating an integration test to check that the data is working based on this very good tutorial.
The tutorial loads sample data in the OnModelCreating. But I was unsure if doing that will repeatedly load data to the DB when running the program.
However although I can get the index page to load, it has the page content, such as the table structure for the data it doesn't have the data from the database.
Using Swagger I copied a sample of data as JSON, saved it to a file, capitalized the first letter of the key to make it the same as the properties (after not doing do was fruitless as well), and tried to add it to the context.
internal static class AddTestData
{
//import json array and add to context
public static void AddMovieData(ApplicationDbContext context)
{
var jsonString = File.ReadAllText("testMoviedata.json");
var list = JsonSerializer.Deserialize<List<Movie>>(jsonString);
{
foreach (var item in list)
{
context.Movie.Add(item);
}
context.SaveChanges();
}
}
}
and tried to add it to the dbcontext in this process in the WebApplicationFactory Class from HERE
public class TestingWebAppFactory<TEntryPoint> : WebApplicationFactory<Program> where TEntryPoint : Program
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
......... stuff deleted for brevity...
using (var appContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>())
{
try
{
appContext.Database.EnsureCreated();
// Seed the database with test data.
AddTestData.AddMovieData(appContext);
}
catch (Exception ex)
{
//Log errors or do anything you think it's needed
throw;
}
}
... still nothin. Page loads, no data loads.
Also why can't I get breakpoints to work in the Integration project?
What am I doing wrong?

Solved!!!
The code was OK,but the data wasn't being deserialised.
I had to move it to the main project and test it there.
The solution is
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
var list = JsonSerializer.Deserialize<Movie[]>(jsonString, options);

Related

EF Core not setting class variables automatically

I want to switch my code to an async implementation. When I want to do this then I notice that my related data gets not set automatically after I retrieve them like it used to do it.
This is the initial function that gets called from an API controller. I used the AddDbContext function to add the dbcontext class via dependency injection into my controller:
public async Task<Application> GetApplicationById(AntragDBNoInheritanceContext dbContext, int id)
{
List<Application> ApplicationList = await dbContext.Applications.FromSqlRaw("Exec dbo.GetApplication {0}", id).ToListAsync();
Application Application = ApplicationList.First();
if(Application != null)
{
await CategoryFunctions.GetCategoryByApplicationID(Application.Id);
}
}
The GetCategoryByApplicationId function loads the related category of an application which is a many to one relation between Category and Application:
public async Task<Category> GetCategoryByApplicationID(int applicationID)
{
var optionsBuilder = new DbContextOptionsBuilder<AntragDBNoInheritanceContext>();
optionsBuilder.UseSqlServer(ApplicationDBConnection.APPLICATION_CONNECTION);
using (var dbContext = new AntragDBNoInheritanceContext(optionsBuilder.Options))
{
List<Category> category = await dbContext.Categories.FromSqlRaw("Exec GetApplicationCategory {0}", applicationID).ToListAsync();
if (category.Any())
{
return category.First();
}
}
return null;
}
When I want to retrieve an application then the field Category is not set. When I did not use async/await it would set the category automatically for me. Of course I could just return the Category Object from the GetCategoryByApplicationId and then say:
Application.Category = RetrievedFromDbCategory;
But this seems a bit unmaintainable compared to the previous behaviour. Why does this happen now and can I do something about it? Otherwise I don't see much benefits on using async/await .

flutter serialize son to list objects throws exception

I have a .net server web api call that I am trying to port the client part to Flutter from Xamarin. mostly impressed with flutter/Dart except the json serialization/deserialization is a pain! my api returns a list of exercise routines that have embedded list of machines. this is pretty simp and normal stuff. my generated JSON looks like :
[
{"id":1,"
Name":"back",
"userid":1,
"cloned":0,
"Machines":
[
{"machineid":2,
"Name":"Leg Extension","PictureUrl":"https://l},
{"machineid":3,"Name":"yoga ball","PictureUrl":"https://
}
I originally tried the manual approach with dart.convert and things worked for my serializing a list of routines. however then I decided to use the code generation as described here my code thru following exception when I called jsonDecode:
type 'List' is not a subtype of type 'Map'
my flutter UI code looks like:
_fetchData() async {
setState(() {
isLoading = true;
});
final response =
await http.get("http://fitnesspal.azurewebsites.net/api/routines");
if (response.statusCode == 200) {
// list = (json.decode(response.body) as List)
// .map((data) => new Routine.fromJson(data))
// .toList();
// final jsonResponse = json.decode(response.body);
try {
String json1 = response.body;
Map map1 = jsonDecode(json1);
var test = Routine.fromJson(map1);
}
catch (e) {
print(e.toString());
}
setState(() {
isLoading = false;
});
} else {
throw Exception('Failed to load photos');
}
}
import 'package:json_annotation/json_annotation.dart';
import 'package:fitnesspal/Models/Machine.dart';
part 'Routine.g.dart';
#JsonSerializable(nullable: false)
class Routine{
final int id;
final String name;
#JsonKey(name: 'Machines')
List<Machine> Machines;
Routine({this.id,this.name,this.Machines});
factory Routine.fromJson(Map<String, dynamic> json) =>
_$RoutineFromJson(json);
Map<String, dynamic> toJson() => _$RoutineToJson(this);
}
I followed the described code generation steps
This doesn't work because json1 is a List of objects, not a Map.
Map map1 = jsonDecode(json1);
Try using this :
List list = jsonDecode(json1);
And get the first element just for testing (in a real scenario you will have to loop the list)
var test = Routine.fromJson(list[0]);
sorry the above was DFU error with stackoverflow. your idea worked but to get the list of routines that I wanted I ended up with:
list = (jsonDecode(response.body) as List)
.map((data) => new Routine.fromJson(data))
.toList();
I then use the routine name in my listBuilder and looks good so feeling pretty good but then I need to pass the embedded machine list to my list of machines widget. so I add a stateful widget called MachineList as follows: notice I setup my constructor to accept the List
class MachineList extends StatefulWidget {
final List<Machine> machines;
MachineList({Key key, this.machines}) : super(key: key);
#override
_MachineListState createState() => _MachineListState(machines);
}
then back in main.dart I want to navigate in the list item ontap :
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MachineList(
machines: list[index].machines)
)
);
lib/main.dart:122:82: Error: The argument type 'dart.core::List<#lib1::Machine>' can't be assigned to the parameter type 'dart.core::List<#lib2::Machine>
OMG where is it getting lib2 from
**** found my issue a case mismatch on the import In Dart, two libraries are the same if, and only if, they are imported using the same URI. If two different URIs are used, I had .../Models/. and ../models
painful learning experience as did not realize Dart was so sensitive as to used to c#

JCL querying form JIRA serivce plugin

I have an JIRA service which runs periodically. I need to look for an certain issues. For this I am using the search service. Because service is running without user context I have no user so I am passing null into search method.
I am able to search the Story type issues from JIRA UI, so they seem to be indexed. But in the plugin the result is always 0 hits.
Not sure if the problem is in null user or something else. This should be a common scenario, but I was not able to find an example.
public class IssueService extends com.atlassian.jira.service.AbstractService {
#ComponentImport
#Inject
private SearchService searchService;
#Override
public void run() {
JqlClauseBuilder jqlClauseBuilder = JqlQueryBuilder.newClauseBuilder();
com.atlassian.query.Query query = jqlClauseBuilder.issueType("Story").buildQuery();
PagerFilter pagerFilter = PagerFilter.getUnlimitedFilter();
com.atlassian.jira.issue.search.SearchResults searchResults = null;
try {
searchResults = searchService.search(null, query, pagerFilter);
} catch (SearchException e) {
throw new RuntimeException(e);
}
List<Issue> issueList = searchResults.getIssues();
}
//rest method omitted
}
Solution for me was to use the following method:
SearchResults searchResults =
searchService.searchOverrideSecurity(null, query, pagerFilter);

Windows Store apps, save and load the state of Bing Maps Pushpins on navigation between pages

I'm making a Windows Store App that asks for user input then produces a bunch of pushpins based on that input. When a pushpin is tapped the app navigates to a page with more detail.
Now the problem i'm having is this:
My pages all inherit from the automatically generated LayoutAwarePage so I could potentially make use of SaveState and LoadState to save the pushpins so they don't get wiped on navigation. The thing is that i can't get the pins to save into the Dictionary object supplied by SaveState.
The error I get is "Value cannot be null" and it's referring to the _pageKey variable in LayoutAwarePage.OnNavigatedFrom() and i don't know why it's happening.
I've tried serialising them into a JSON string so i can deserialise it in LoadState, but i get the same result using a string or a List of UIelement.
I think this is all due to my lack of understanding of how SaveState, LayoutAwarePAge and SuspensionManager work. I thought what i was doing would work as the Dictionary is only asking for a string and an object.
I'm not using any other methods from LayoutAwarePage so if there is a better way than using SaveState and LoadState, I'm all ears.
These are the two versions of SaveState i've tried:
Using JSON
protected override void SaveState(Dictionary<String, Object> pageState)
{
List<string> pindata = new List<string>();
List<string> serialisedpins = new List<string>();
foreach (Pushpin ele in map.Children)
{
pindata = ele.Tag as List<string>;
serialisedpins.Add(JsonConvert.SerializeObject(pindata));
}
string jasoned = JsonConvert.SerializeObject(serialisedpins);
pageState["pins"] = jasoned;
}
using a List of UIElement
protected override void SaveState(Dictionary<String, Object> pageState)
{
List<UIElement> pins = new List<UIElement>(map.Children);
pageState["pins"] = pins;
}
The error you're getting (_pagekey value cannot be null) is not really related to what you're saving into the Dictionary. The exception is most likely being thrown in OnNavigateFrom() method of LayoutAwarePage:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
var frameState = SuspensionManager.SessionStateForFrame(this.Frame);
var pageState = new Dictionary<String, Object>();
this.SaveState(pageState);
frameState[_pageKey] = pageState; // <-- throws exception because _pageKey is null
}
If you take a look at the rest of the code of LayoutAwarePage you'll find out the value of _pageKey is being set in OnNavigatedTo method of LayoutAwarePage:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Returning to a cached page through navigation shouldn't trigger state loading
if (this._pageKey != null) return;
var frameState = SuspensionManager.SessionStateForFrame(this.Frame);
this._pageKey = "Page-" + this.Frame.BackStackDepth; <-- this line sets the _pageKey value
if (e.NavigationMode == NavigationMode.New)
{
// Clear existing state for forward navigation when adding a new page to the
// navigation stack
var nextPageKey = this._pageKey;
int nextPageIndex = this.Frame.BackStackDepth;
while (frameState.Remove(nextPageKey))
{
nextPageIndex++;
nextPageKey = "Page-" + nextPageIndex;
}
// Pass the navigation parameter to the new page
this.LoadState(e.Parameter, null);
}
else
{
// Pass the navigation parameter and preserved page state to the page, using
// the same strategy for loading suspended state and recreating pages discarded
// from cache
this.LoadState(e.Parameter, (Dictionary<String, Object>)frameState[this._pageKey]);
}
}
Usually the reason for that is that you're overriding OnNavigatedTo in your own page without calling base.OnNavigatedTo(e) inside it. The basic pattern of overriding it should always be:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
// the rest of your own code
}
This will make sure the base implementation will execute and set the _pageKey value as well as call LoadState() to load the previously saved state if there's any.

Generate test data in Raven DB

I am looking for a preferred and maintainable way of test data generation in Raven DB. Currently, our team does have a way to do it through .NET code. Example is provided.
However, i am looking for different options. Please share.
public void Execute()
{
using (var documentStore = new DocumentStore { ConnectionStringName = "RavenDb" })
{
documentStore.Conventions.DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites;
// Override the default key prefix generation strategy of Pascal case to lower case.
documentStore.Conventions.FindTypeTagName = type => DocumentConvention.DefaultTypeTagName(type).ToLower();
documentStore.Initialize();
InitializeData(documentStore);
}
}
Edit: Raven-overflow is really helpful. Thanks for pointing out to the right place.
Try checking out RavenOverflow. In there, I've got a FakeData project that has fake data (both hardcoded AND randomly generated). This can then be used in either my Tests project or the Main Website :)
Here's some sample code...
if (isDataToBeSeeded)
{
HelperUtilities.CreateSeedData(documentStore);
}
....
public static void CreateSeedData(IDocumentStore documentStore)
{
Condition.Requires(documentStore).IsNotNull();
using (IDocumentSession documentSession = documentStore.OpenSession())
{
// First, check to make sure we don't have any data.
var user = documentSession.Load<User>(1);
if (user != null)
{
// ooOooo! we have a user, so it's assumed we actually have some seeded data.
return;
}
// We have no users, so it's assumed we therefore have no data at all.
// So let's fake some up :)
// Users.
ICollection<User> users = FakeUsers.CreateFakeUsers(50);
StoreFakeEntities(users, documentSession);
// Questions.
ICollection<Question> questions = FakeQuestions.CreateFakeQuestions(users.Select(x => x.Id).ToList());
StoreFakeEntities(questions, documentSession);
documentSession.SaveChanges();
// Make sure all our indexes are not stale.
documentStore.WaitForStaleIndexesToComplete();
}
}
....
public static ICollection<Question> CreateFakeQuestions(IList<string> userIds, int numberOfFakeQuestions)
{
.... you get the idea .....
}