Why isn't my test method executing? - nunit

I have a fairly complex integration test that requires a lot of data in each distinct test case.
My test case class is as follows:
public class TestCases
{
public static IEnumerable MatchingCases
{
get
{
yield return
new SearchSetup
{
MinimumMatches = 1,
BulletinSetups = new List<BulletinSetup>
{
new BulletinSetup
{
ParameterSetups = new List<ParameterSetup>
{
new ParameterSetup
{
FieldName = "Number",
ParameterName = "#Number",
Value = "TBS1001" + DateTime.Now.ToLocalTime()
}
}
}
},
FilterValues = new Dictionary<string, object> { { "Number", "TBS1001" } }
};
}
}
}
The header of my test method is:
[Test, TestCaseSource(typeof(TestCases), "MatchingCases")]
public void Search_VariableFilter_NoAccountTeam_ResultIncludesExpected(SearchSetup searchSetup)
When I run the test, it returns inconclusive. When I step thru the code, I find that the MatchingCases property getter is being accessed, and the yield return statement executes w/o issue, but the test method itself is not called - or rather, not predictably.
See, I wrote this question up once already, then I tried moving the test class out of the testfixture scope. When I did that, the code executed once, and so I dumped my question. Then it stopped executing anymore...
Why isn't my test method being called?
Edit: Anticipating the question - these are the supporting classes being used:
public class ParameterSetup
{
public string ParameterName { get; set; }
public string FieldName { get; set; }
public object Value { get; set; }
}
public class BulletinSetup
{
public List<ParameterSetup> ParameterSetups { get; set; }
}
public class SearchSetup
{
public List<BulletinSetup> BulletinSetups { get; set; }
public int MinimumMatches { get; set; }
public Dictionary<string, object> FilterValues { get; set; }
}
Update - next day
After closing and reloading Visual Studio, and rerunning the test with no changes of any kind, the test code executes, repeatedly. I'm beginning to suspect this was a transitory glitch.

Since reloading VS the test method executes fine. I'm chalking it up as a glitch to close this question out.

Related

Update Navigation Property with Entity.CurrentValues.SetValues

I have a Kalem Entity with a collection of DigerKalemMaliyetleri property, which is a collection of MaliyetBirimi objects. DigerKalemMaliyetleri is of JSON type and stored at the same table as a JSON column.
public class Kalem
{
public int Id { get; set; }
[Column(TypeName = "json")]
public ICollection<MaliyetBirimi> DigerKalemMaliyetleri { get; set; }
}
public class MaliyetBirimi
{
public int? DovizCinsi { get; set; }
public decimal? Maliyet { get; set; }
}
When I try to update entity with only DigerKalemMaliyetleri property changed:
DataContext.Entry<Kalem>(first).CurrentValues.SetValues(second);
SQL Update command isn't executed and database record is not updated.
How could I update the entity without explicitly setting DigerKalemMaliyetleri property?
Regards
I had the same problem, you cann't actually use SetValues to update navigation property, you nead instead use DataContext.Update(YourNewObj) and then DataContext.SaveChanges();, or if you want to use SetValues approach, you need:
-Get the exist entry
Kalem existObj = DataContext.Kalems.Find(YourNewObj.Id);
-Loop in navigations of updating entry and the existing one to set the values of updating entry:
foreach(var navObj in DataContext.Entry(YourNewObj).Navigations)
{
foreach(var navExist in DatatContext.Entry(existObj).Navigations)
{
if(navObj.Metadata.Name == navExist.MetaData.Name)
navExist.CurrentValue = navObj.CurrentValue;
}
}
-Update also changes of direct properties:
DataContext.Entry(existObj).CurrentValues.SetValues(YourNewObj);
-Save your Updating:
DataContext.SaveChanges();
You can also check if you need to load your Navigations before going in foreach loop, otherwise you will get an error.
Please if you see beter scenario, correct me.
It's hard to know exactly what you're doing without a complete code sample. Note also that you're trying to set all properties of first from second, including e.g. the Id, which is probably not what you want.
Here's a complete code sample which works for me:
await using (var ctx = new BlogContext())
{
await ctx.Database.EnsureDeletedAsync();
await ctx.Database.EnsureCreatedAsync();
ctx.Kalem.Add(new()
{
DigerKalemMaliyetleri = new List<MaliyetBirimi>()
{
new() { DovizCinsi = 1, Maliyet = 2 }
}
});
await ctx.SaveChangesAsync();
}
await using (var ctx = new BlogContext())
{
var first = ctx.Kalem.Find(1);
var second = new Kalem
{
DigerKalemMaliyetleri = new List<MaliyetBirimi>()
{
new() { DovizCinsi = 3, Maliyet = 4 }
}
};
ctx.Entry(first).Property(k => k.DigerKalemMaliyetleri).CurrentValue = second.DigerKalemMaliyetleri;
await ctx.SaveChangesAsync();
}
public class BlogContext : DbContext
{
public DbSet<Kalem> Kalem { get; set; }
static ILoggerFactory ContextLoggerFactory
=> LoggerFactory.Create(b => b.AddConsole().AddFilter("", LogLevel.Information));
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseNpgsql(#"Host=localhost;Username=test;Password=test")
.EnableSensitiveDataLogging()
.UseLoggerFactory(ContextLoggerFactory);
}
public class Kalem
{
public int Id { get; set; }
[Column(TypeName = "json")]
public ICollection<MaliyetBirimi> DigerKalemMaliyetleri { get; set; }
}
public class MaliyetBirimi
{
public int? DovizCinsi { get; set; }
public decimal? Maliyet { get; set; }
}

How to access class properties using interface object which are not defined in the interface?

I am new to this forum. Now-days I am studying design patterns. I learnt about factory pattern and implemented simple example as shown below.
public interface IPlc
{
string Name { get; set; }
void Testping();
}
Public AbbPlc : IPlc
{
string Name { get; set; }
string slotnumber { get; set; }// Property relevant with this class
public void Testping()
{
console.writeline("ping executed successfully");
}
}
Public SiemensPlc : IPlc
{
string Name { get; set; }
string Racknumber { get; set; }// Property relevant with this class
public void Testping()
{
console.writeline("ping executed successfully");
}
}
//In Main Program
var objAbb = new IPlc() //Created object from interface
objAbb.Name = "46IC-PLC"; //Works OK
objAbb.slotnumber "3"; //Not works
var objSiemens = new IPlc() //Created object from interface
objSiemens.Name = "45IC-PLC"; //Works OK
objSiemens.Racknumber "5"; //Not works
Could you please tell me why these two methods doesn't work?
What I have to do to access properties from Interface object?
Do I need to use one more pattern with factory like decorator?

Using sets of Entity Framework entities at runtime

I have an EF6 setup against a sql server db with about 60 tables in it.
I have entities for each table. What i'm trying to do is run the same method against a set of these entities that will be known at runtime.
The method is a qa/qc routine that does some data check on particular fields that are assured to be in each table.
I guess what i want to do is make the entity a parameter to the method so i can call it consecutive times.
I would also want to make a set of entities to pass as the parameter.
something like this:
List<string> entList = new List<string>(){"Table1","Table2","Table3"};
foreach (entName in entList)
{
//create an entity with the string name
//call myQAQCMethod with the entity
}
MyQAQCMethod (entity SomeEntity)
{
//run against this entity
doQAQC(SomeEntity);
}
Can this be done? Is it a job for reflection?
EDIT
using (var context = new Context())
{
var results = context.EntityAs.Where(a => a.Prop1 == e.Prop1)
.Where(a => a.Prop2 == e.Prop2)
.Select(a => new
{
APropertyICareAbout = a.Prop1,
AnotherPropertyICareAbout = a.Prop2
}).ToArray();
}
is precisely want i want to do. The thing is I want to avoid typing this loop 60 times. I think i'm looking for a way to "feed" a set of entities to this single method.
Also, thank you very much for helping me. I'm learning a lot.
You need to abstract an interface (entity framework won't even notice):
interface IQaQcable
{
int CommonInt { get; set; }
string CommonString { get; set; }
}
public class EntityA : IQaQcable
{
public int Id { get; set; }
public int CommonInt { get; set; }
public string CommonString { get; set; }
// other properties and relations
}
public class EntityB : IQaQcable
{
public int Id { get; set; }
public int CommonInt { get; set; }
public string CommonString { get; set; }
// other properties and relations
}
// in some unknown utility class
void MyQaQcMethod<T>(T entity) where T : IQaQcable
{
doSomethingWithIQaQcableProperties(entity.CommonInt, entity.CommonString);
}
// in some unknown test class
void Test()
{
var entities = new List<IQaQcable> { new EntityA(), new EntityB() };
foreach (var e in entities)
MyQaQcMethod(e);
}
Now, you could extract a base class from which each derives that actually implements the CommonInt and CommonString properties for each entity needing them, but that can get kind of tricky with Table-Per-Type/Table-Per-Hierarchy, so I'd start with this, and then consider introducing either an abstract or concrete base class as an improvement.
EDIT
Maybe your looking for something simpler than I first thought, based on your last comment.
Let's give ourselves what the DbContext for this might look like:
class Context : DbContext
{
public virtual DbSet<EntityA> EntityAs { get; set; }
public virtual DbSet<EntityB> EntityBs { get; set; }
}
So, it could just be that you wish to do this:
using (var context = new Context())
{
var results = context.EntityAs.Where(a => a.Prop1 == e.Prop1)
.Where(a => a.Prop2 == e.Prop2)
.Select(a => new
{
APropertyICareAbout = a.Prop1,
AnotherPropertyICareAbout = a.Prop2
}).ToArray();
}
Keeping in mind, if there is some set of properties in common across entity classes, you could still do something like the following:
IEnumerable<T> MyQaQcMethod(IQueryable<T> entities, T referenceEntity) where T : IQaQcAble
{
return entities.Where(e => SomePredicate(e, referenceEntity));
}
void Test()
{
using (var context = new Context())
{
// EntityA implements IQaQcAble
var resultsForA = MyQaQcMethod(context.EntityAs, defaultEntity).ToArray();
// so does EntityB, so can call with either
var resultsForB = MyQaQcMethod(context.EntityBs, defaultEntity).ToArray();
}
}
Keep in mind, to avoid modifying the generated entity classes, you could implement the interface members — and the interface — in a separate source file using partial classes. E.g.
// IQaQcAble.cs
internal interface IQaQcAble
{
int CommonInt { get; set; }
string CommonString { get; set; }
}
// a class whose existing property names match the interface
public partial class EntityA : IQaQcAble
{
int IQaQcAble.CommonInt
{
get { return CommonInt; }
set { CommonInt = value; }
}
string IQaQcAble.CommonString
{
get { return CommonString; }
set { CommonString = value; }
}
}
// a class whose property names differ
public partial class EntityB : IQaQcAble
{
int IQaQcAble.CommonInt
{
get { return SomeOtherInt; }
set { SomeOtherInt = value; }
}
string IQaQcAble.CommonString
{
get { return SomeOtherInt.ToString(); }
set { SomeOtherInt = Convert.ToInt32(value); }
}
}

Custom Model Binder, asp.net mvc 2 rtm 2, Parsing ID to ComplexModel

I have found myself with at little problem, and I think a custom model binder is the way to go.
My Domain model looks like this,readly standard
I got a Page and a Template. The Page has the Template as a ref.
So the Default asp.net mvc Binder, does not know how to bind it, therefore I need to make some rules for it. (Custom Model Binder)
public class PageTemplate
{
public virtual string Title { get; set; }
public virtual string Content { get; set; }
public virtual DateTime? Created { get; set; }
public virtual DateTime? Modified { get; set; }
}
public class Page
{
public virtual string Title { get; set; }
public virtual PageTemplate Template { get; set; }
public virtual string Content { get; set; }
public virtual DateTime? Created { get; set; }
public virtual DateTime? Modified { get; set; }
}
So I have Registreted the ModelBinder in globals.asax
ModelBinders.Binders.Add(typeof(Cms.Domain.Entities.Page),
new Cms.UI.Web.App.ModelBinders.PageModelBinder(
new Services.GenericApplicationService<Cms.Domain.Entities.Page>().GetEntityStore()
)
);
My ModelBinder tage a paremeter, witch is my Repository, where I get all my Entities ( Page, Template )
My Controller for a Page looks like this.
I have posted into a Create Controler, it does not matter for now, if it was a Update method.
Since I in this case have a dropdown, that represents the Template, I will get an ID in my form collection.
I then call: TryUpdateModel and I got a hit in my PageModelBinder.
[AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken]
[ValidateInput(false)]
public ActionResult Create(FormCollection form)
{
Page o = new Page();
string[] exclude = new { "Id" }
if (base.TryUpdateModel<Page>(o, string.Empty, null, exclude, form.ToValueProvider()))
{
if (ModelState.IsValid)
{
this.PageService.Add(o);
this.CmsViewData.PageList = this.PageService.List();
this.CmsViewData.Messages.AddMessage("Page is updated.", MessageTypes.Succes);
return View("List", this.CmsViewData);
}
}
return View("New", this.CmsViewData);
}
So I end op with the Model Binder.
I have search the internet dry for information, but im stock.
I need to get the ID from the FormCollection, and parse it to at Model from my IEntityStore.
But how ?
public class PageModelBinder : IModelBinder
{
public readonly IEntityStore RepositoryResolver;
public PageModelBinder(IEntityStore repositoryResolver)
{
this.RepositoryResolver = repositoryResolver;
}
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException("bindingContext");
}
if (modelType == typeof(Cms.Domain.Entities.Page))
{
// Do some magic
// Get the Id from Property and bind it to model, how ??
}
}
}
// Dennis
I hope, my problom is clear.
Did find a work around.
I download the sourcecode for asp.net r2 rtm 2
And did copy all code for the default ModelBinder, and code it need. Did some minor change, small hacks.
the work around is doing a little hack in this method:
[SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.Web.Mvc.ValueProviderResult.ConvertTo(System.Type)",
Justification = "The target object should make the correct culture determination, not this method.")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
Justification = "We're recording this exception so that we can act on it later.")]
private static object ConvertProviderResult(ModelStateDictionary modelState, string modelStateKey, ValueProviderResult valueProviderResult, Type destinationType)
{
try
{
object convertedValue = valueProviderResult.ConvertTo(destinationType);
return convertedValue;
}
catch (Exception ex)
{
try
{
// HACK if the binder still fails, try get the entity in db.
Services.GenericApplicationService<Cms.Domain.Entities.PageTemplate> repo;
repo = new Services.GenericApplicationService<Cms.Domain.Entities.PageTemplate>();
int id = Convert.ToInt32(valueProviderResult.AttemptedValue);
object convertedValue = repo.Retrieve(id);
return convertedValue;
}
catch (Exception ex1)
{
modelState.AddModelError(modelStateKey, ex1);
return null;
}
}
}
This question is closed.

1 to 1 Object Relations in EF4 Code First

I have a parent object book, and a property of that object is publisher. Everytime I ad a book, it is adding a new publisher, even if the publisher already exists. Can someone tell me how to add the book and instead of adding the publisher again, just reference an existing one? The code i am using is below... Thanks in advance!
public class Book
{
public int BookID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime CreateDate { get; set; }
public virtual Publisher Publisher { get; set; }
}
public class Publisher
{
public int PublisherID { get; set; }
public string Address { get; set; }
}
public class SqlCEDataStore : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Publishers> Publishers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.IncludeMetadataInDatabase = false;
}
}
public class TimeSinkRepository : IRepository<Book>
{
private static SqlCEDataStore context = new SqlCEDataStore();
public int Add(Book entity)
{
context.Books.Add(entity);
return context.SaveChanges();
}
}
var book = new Book()
{
Title = "New Title",
Description = "New Description",
CreateDate = DateTime.Now,
Publisher = new Publisher() { PublisherID = 1 }
};
var repository = new BookRepository();
var result = repository.Add(book);
The problem is in the line:
Publisher = new Publisher() { PublisherID = 1 }
Object context doesn't know that this is existing publisher. It is newly created entity so Object context will perform insert operation. You have to say object context that the publisher object is not newly created. One way to do that is modification of your Add method:
public int Add(Book entity)
{
context.Books.Add(entity);
// 0 means new one, other values mean existing one
if (entity.Publisher.PublisherID > 0)
{
context.ObjectStateManager.ChangeObjectState(entity.Publisher, EntityState.Unchanged);
}
context.SaveChanges();
}
It you can solve this by making sure the Publisher is attached to Publishers context before adding the Book entity (this way it knows it's a Publisher from the dbcontext and not a new one that it needs to add (again))
context.Publishers.Attach(book.Publisher); // This is only possible if the Publisher is not new
context.Books.Add(book);
the problem is in this line
Publisher = new Publisher() { PublisherID = 1 }
You should do a fetch method so something like this
- Get the Publisher you want from the context (eg where id = 1)
- Set the returned object as the publisher for your new book object
- The context should sort the rest out for you. when you save the book. (no need to mess with the object state manager)
Good luck, if you cant get this working put up some code of it and i will help you though it.