This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
Hello, I am trying to mock some classes that are derived from Entity. In particular the property that we need set is Id. This is a non-virtual property, so we can't mock it, and according to what I've read in this forum it cannot be overriden anywhere. Again, in this forum it mentions two methods we can use: GeneratedId and OnMockSavingEntity. I've tried using OnMockSavingEntity, but this does not appear to set the identifier. And GeneratedId() is no good as this would us to override each and every entity that we want to mock. Is there anyway of setting id or getting the id to automatical populate other than these two methods?
Craig |
|
|
OnMockSavingEntity just simulates the events and state changes associated with a save -- it doesn't provide control over the ID (the ID is usually allocated earlier, when the entity is associated with a unit of work). Therefore, GeneratedId() is currently the only way of controlling the ID allocated to your entities. Could you say a bit more about why you need to set the IDs of your test entities? Is it a matter of wishing to bypass the database-bound identity methods for performance reasons, or are you actually dependent on allocating specific IDs? We are planning to improve testability support in LightSpeed 3, including offering ID control, so it's useful to understand people's use cases. Thanks! |
|
|
Hi Ivan,
If I may add to this post. I have an interest in assigning ID's to entities. I've tried the solution posted on your blog post (http://www.mindscape.co.nz/blog/index.php/2009/03/04/testing-with-lightspeed/) but it doesn't set the Id's correctly. Here is an example.
We have an entity class called Vozilo (croatian word for Car).
public class VoziloStub : Vozilo
{
private int _overrideId;
public new int Id
{
get
{
return _overrideId;
}
set
{
_overrideId = value;
}
}
}
When I try to load the Vozilo objects from the XML file, I use the following method:
public IQueryable LoadVozila()
{
List res = new List();
XmlDocument doc = new XmlDocument();
doc.Load(@"C:\Users\milivojm\Documents\Visual Studio 2008\Projects\OsnovnaSredstva\IPS.OsnovnaSredstva.Test\Data\Vozila.xml");
foreach (XmlElement e in doc.ChildNodes[0].ChildNodes)
{
VoziloStub v = new VoziloStub();
v.Id = Convert.ToInt32(e.GetAttribute("Id"));
v.DatumPrveRegistracije = Convert.ToDateTime(e.GetAttribute("DatumPrveRegistracije"));
v.DatumZadnjegServisa = Convert.ToDateTime(e.GetAttribute("DatumZadnjegServisa"));
v.DatumZadnjeRegistracije = Convert.ToDateTime(e.GetAttribute("DatumZadnjeRegistracije"));
v.Kilometara = Convert.ToDecimal(e.GetAttribute("Kilometara"));
v.KorisnikId = Convert.ToInt32(e.GetAttribute("KorisnikId"));
v.Naziv = e.GetAttribute("Naziv");
v.Registracija = e.GetAttribute("Registracija");
res.Add(v);
}
return res.AsQueryable();
}
The _overrideId field is set correctly, but method returns IQueryable and it looks for GetId (Id property) of Vozilo class, not the new implementation of Id in VoziloStub. So when I pass the list to methods that are querying over Vozilo, and look for one specific with Id = 16, I get no objects in return. Meaning there is really no way I can mock the Vozilo using this technique.
The method I'm unit testing is:
public void PridruziPopravkeVozilu(List list, int voziloId, DateTime datumRacuna)
{
// throw new NotImplementedException("Datum računa se treba obraditi");
int year = DateTime.Now.Year;
int? brojRacuna;
decimal pdv = 0;
if (unit.ServisVozilas.Count() > 0)
{
brojRacuna = (from sv in unit.ServisVozilas
select sv.BrojRacuna).Max();
brojRacuna = brojRacuna + 1;
}
else
brojRacuna = 1;
foreach (ServisVozila sv in list)
{
sv.Datum = DateTime.Now.Date;
sv.BrojRacuna = brojRacuna;
pdv += sv.Cijena * _pdvPostotak;
}
Vozilo v = (from voz in unit.Vozilos
where voz.Id == voziloId
select voz).First();
v.Servisi.AddRange(list);
// Dodaj PDV
ServisVozila pdvIznos = new ServisVozila();
pdvIznos.BrojRacuna = brojRacuna;
pdvIznos.Cijena = pdv;
pdvIznos.Datum = DateTime.Now.Date;
pdvIznos.OpisUsluge = "PDV";
pdvIznos.Jedinica = "-";
pdvIznos.Kolicina = 1;
v.Servisi.Add(pdvIznos);
unit.SaveChanges();
MailController mailController = new MailController();
mailController.SendServiceBillNotification(v, brojRacuna);
}
Inside there is a LINQ query going like this:
Vozilo v = (from voz in unit.Vozilos
where voz.Id == voziloId
select voz).First();
This is where the unit test fails because the ID is always 0 (the Vozilo class ID), and I'm looking for 16 (that's written in VoziloStub.ID).
Basically, I am unable to use polymorphism due to ID being non virtual.
Is there anything I can do to solve this problem?
Thank you in advance.
Milivoj Milani
Croatia
|
|
|
I swear I formatted correctly the entire post, but it displays like this.
|
|
|
Hi Milivoj, I found a work-around for this problem, although its not a supported approach. basically the trick is to use reflection to set the underlying field: var type = typeof(Entity<Guid>); var idField = type.GetField("_id", BindingFlags.NonPublic | BindingFlags.Instance);idField.SetValue(entity, Guid.NewGuid());Replace Guid with the type of the key field and this will work. Normally I put this into a helper method in our unit test module, so I don't have to keep rewriting it.
Craig |
|
|
Craig, thank you very much. I will try it.
Btw. sorry about the post before, the problem was in using Google Chrome instead of IE8. In Chrome there is no toolbar. |
|
|
Thanks for posting Craig - much appreciated. That's the best way for now, otherwise we have an API for helping with the testing coming in LS 3.0 as we realise it's less than optimal currently. No need to be sorry Milivoj, we need to update the editor in Community Server since it's getting a bit old! Cheers, John-Daniel Trask |
|
|
Just for completeness, another possible approach is, in the derived stub class, to override GeneratedId(). E.g. public class VoziloStub : Vozilo { However this will only take effect when you add the entity to the unit of work, whereas Craig's approach allows you to control the Id at any point during the lifecycle. |
|