Scoping contant FsCheck generator to each test - fscheck

I am trying to test a domain model for a SaaS application with FsCheck and XUnit. Each model entity has a column TenantId with some unique tenant identifier. There are numerous Asserts checking that TenantIds are not mixed up.
For now, I have this TenantId generated with Gen.Constant generator. However, this is fixing the value for the whole test run, so all tests are using the same TenantId. It would be more convenient if this value would be reset for each test but stay constant within a test.
To be more specific, let's say that there are two entities and the class for TenantId:
public record TenantId(Guid value);
public record EntityA(TenantId TenantId, string SomeString);
public record EntityA(TenantId TenantId, int SomeNumber);
And some xUnit tests annotated with [Property]:
[Property]
public void PropertyTest1(EntityA a, EntityB b) => Assert(a.TenantId == b.TenantId);
[Property]
public void PropertyTest2(EntityA a, EntityB b) => Assert(a.TenantId == b.TenantId);
Is it possible to configure an Arbitrary for TenantId type so it will different values for PropertyTest1 and PropertyTest2, but constant value inside these tests?

Related

Using HttpPatch without violating encapsulation

I have problem about HttpPatch which violate encapsulation of domain model. I using ASP.NET Core
Let's start with an example: I have a customer domain model which has some attributes and behaviour to imagine it better
public class Customer
{
public Customer(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public string Firstname { get; private set; }
public string Lastname { get; private set; }
public System.DateTime BirthDate { get; private set; }
public void UpdateName(string firstname, string lastname)
{
/*
* Some validations here for example first name first latter should be uppercase and so on..
*/
Firstname = firstname;
Lastname = lastname;
}
public void UpdateBirthDate(System.DateTime BirthDate)
{
/*
* Some validations here for example age must be greater than 18
*/
this.BirthDate = BirthDate;
}
}
As you can see above we have a customer domain model which has private setters and has method which is used to update domain model properties. So to update Firstname and Lastname you gonna call "UpdateName" - method which validates data and after that it will update this model. Also it could throw some domain events if necessary.
Also I'm using Rest architecture in my API. So I have some method where I need to update my customer model partially here is also example:
[HttpPatch]
public async Task<IActionResult> Update([FromBody] JsonPatchDocument<WorkDay> document)
{
var testCustomer = new Customer();
document.ApplyTo(testCustomer);
return Content("Success");
}
So right now let's talk about problem about above code. Let's imagine that testCustomer pulled from storage. After that we update our storage customer by calling ApplyTo. The problem here actually is that it directly sets values to appropriate property which violates encapsulation also the problem in this approach is that it is not calling my methods to throw some domain events or do some validations and so on...
What is workaround of this problem ? Is there any extension which helps me to map those changes to appropriate methods ?
The problem here actually is that it directly sets values to appropriate property which violates encapsulation
The semantics of the HTTP methods are those of a document store. The client has a representation of the resource, it wants the server's representation to match. The entire exchange is fundamentally anemic.
Thus, you end up running into concerns similar to those which encouraged task based user interfaces, which is to say exchanging messages that describe domain semantics, rather than document semantics.
Options:
You can stay with the document semantics, and write code to compute the differences between the server's representation of the document and the client's, translate that difference into domain messages, and apply them to the model.
You can replace the patch document -- instead of using json-patch, you could use your own domain specific patch media type, that describes changes in domain semantics. That makes things easy for the server, but you lose support for general purpose components.
You can change your resource model -- instead of sending changes to the document that is the representation of the domain model, you can send changes to the document that is the representation of the messages being sent to the domain model.
You can use form semantics (POST) to describe client changes, rather than using remote authoring semantics
With information that doesn't belong to you (your model isn't the authority for FirstName or BirthDate -- you are just caching a copy of data provided to you), you might consider separating the model (their data is not the same as our data), or performing the validation on the input (which is to say, walking through the patch-document first, then applying the changes to the model).
But no joke; there are some real tensions when you try to cross from the document domain into your model. See Webber 2011 for more.

Corda Tokens SDK: "There is a token group with no assigned command" error

I already solved this problem, but I would like to understand why it occurred in the first place:
1. I'm using the Java template of Tokens SDK
2. I created my own token type
3. I modified ExampleFlowWithFixedToken class to issue my new token
4. When I ran start ExampleFlowWithFixedToken amount: 100, recipient: PartyB, I got the error: There is a token group with no assigned command
5. Initially my new token class didn't implement the equals() method, when I added it; the error was gone and I was able to issue my token.
Why adding that method, fixes the problem?
public class MyTokenType implements TokenType {
private final int fractionDigits = 6;
private final String tokenIdentifier = "MY_TOKEN";
#NotNull
#Override
public BigDecimal getDisplayTokenSize() {
return BigDecimal.ONE.scaleByPowerOfTen(-fractionDigits);
}
#Override
public int getFractionDigits() {
return fractionDigits;
}
#NotNull
#Override
public Class<?> getTokenClass() {
return this.getClass();
}
#NotNull
#Override
public String getTokenIdentifier() {
return tokenIdentifier;
}
#Override
public boolean equals(Object obj) {
return obj instanceof MyTokenType;
}
}
ExampleFlowWithFixedToken calls the built-in IssueTokens Flow.
This flow , builds the transaction internally specifying input, output states, commands(IssueCommand in this case).
Next step is to verify the contract.
Before verifying the contracts we group the input/output tokens by the issuer.
Each group is then assigned a token command.
This is done because if a transaction contains more than one type of token, they need to grouped by IssuedTokenType.
Also note same token type issued by different issuers are not fungible.
Hence the grouping by IssuedTokenType is required.
Once we have the groups by IssuedTokenType, contract verification is done separately for each group.
When we try to assign a token command to each group , we compare the IssuedTokenType in command to one in our groups.
So if we dont override equals method, none of the IssuedTokenType from the groups will match to the one in the TokenCommand.
Hence the group will not be assigned any TokenCommand.
Each group should at least have one command. If there isn’t then we would not know what to do with that group. Hence it fails saying "There is a token group with no assigned command"
Hope that helps!

An exception of type 'Microsoft.EntityFrameworkCore.DbUpdateException' occurred in Microsoft.EntityFrameworkCore.dll

I am having trouble at very long time. Lets imagine this example:
public class Coordinate {
public int id {get;set;}
public int x {get;set;}
public int y {get;set;}
}
public class Planet {
public int id {get;set;}
public string name {get;set;}
public Coordinate coordinate {get;set;}
}
I have created two models, and the model Planet has the model Coordinate as attribute.
Now imagine somewhere in the code I create one coordinate and it is stored in database.
Imagine this is the coordinate:
Coordinate c = new Coordinate();
c.x = 1;
c.y = 2;
Then I add it to my database and it is saved.
But when I create a planet and I do:
planet.coordinate = c;
And then I try to add it to database I have the following error:
An exception of type 'Microsoft.EntityFrameworkCore.DbUpdateException'
occurred in Microsoft.EntityFrameworkCore.dll but was not handled in
user code
Additional information: An error occurred while updating the entries.
See the inner exception for details.
I know I can change the attribute public Coordinate coordinate to public int coordinate_id but I want to do this with the Coordinate model instead.
I am using ASP NET CORE 1.0
Cumps
Your problem is that at this point, c already has an Id.
With planet.Add, the planet and all coordinates attached to it will be set to Added in your DbSet's and upon calling SaveChanges, insert statements will be created. (Here I assume an autoincrement on your column and your Id property)
When SaveChanges is completed, EF will see that the planet is in the database, but the Id of the just added coordinate is different (it was altered by DBMS, so now the coordinate is twice in your database, with two different Id's), so it will expect something went wrong and throw this exception.
When you don't have problems with duplicate entries, set the Id to null or 0. Otherwise, there are two solutions:
-Set only the FK property, not the navigation property
or
-Call SaveChanges only once (for example, just add the planet, however with added coordinates relationship fixup should lead to the same result)
Having a look at the inner exception will give you a more detailed look at what is going wrong.
To do this, in debug mode, when the exception shows. Click view detail and follow the tree until you find inner exception.
There may be duplicate rows, primary key issues or structure issues.
I was having the same problem and I realized that I was creating more than only one instance to access the database.
So the solution I took was creating a class that made only one access.
class SingletonContext {
private static Context _context;
public static Context GetInstance() {
if (_context == null) {
_context = new Context();
}
return _context;
}
}
And in every access to the database layer I call the GetInstance(), like this:
private static Context _context = SingletonContext.GetInstance();
I also got the similar error, while creating the post method but I resolved this by doing the following
Make sure that you have included the following code in
Constructor
In this import the interface file of which the foreign is key belongs to
HttpPost method
[HttpPost]
[ProducesResponseType(204)]
[ProducesResponseType(400)]
[ProducesResponseType(404)]
//IMPORTANT TO INCLUDE [FromQuery]
public IActionResult CreateBatch([FromQuery] int trackId,
[FromBody] BatchDto batchCreate)
{
if(batchCreate == null)
return BadRequest(ModelState);
var batch = _batchInterface.GetBAtches()
.Where(c => c.batchName.Trim().ToLower() ==
batchCreate.batchName
.TrimEnd().ToLower());
if (batch == null)
return BadRequest(ModelState);
var batchMap = _mapper.Map<Batch>(batchCreate);
batchMap.track = _trackInterface.GetTrack(trackId); //Important
if (!ModelState.IsValid)
return BadRequest(ModelState);
if(!_batchInterface.CreateBatch(batchMap))
{
ModelState.AddModelError("", "Something went in the
creation of batch");
return StatusCode(500, ModelState);
}
return Ok("Successfully created Batch");
}

spring mvc how to store commonly-used collections

This is an architecture question. I have Spring MVC web application that holds about a dozen collections that are rarely changed but that are often used in many-to-one relationships and for populating the drop-down selects that set the values of those properties. (For example: country, region, status types, etc).
In terms of performance and memory use, how should the app make these collections available?
At the moment I have a singleton wrapper class like the following:
#Component("collectionWrapper")
public class CollectionWrapper {
Map<Integer, Country> countries;
Map<Integer, User> users;
Map<Integer, Office> offices;
Map<Integer, Status> statuses
DAOService daoService;
public CollectionWrapper() {}
#Autowired(required=true)
public CollectionWrapper(DAOService daoService) {
this.daoService=daoService;
loadCountriesFromDao();
loadUsersFromDao();
loadOfficesFromDao();
loadStatusesFromDao();
}
public void loadCountriesFromDao() {
countries=daoService.getCountries();
}
// etc...
}
In the rare cases that an item in one of the collections is changed, the controller responsible for making the change calls collectionWrapper.loadCountriesFromDao(), for example.
Finally, the main objects that the app deals with have properties that map to these "reference objects", like so:
#Entity
public class Event {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id", nullable = false)
private Integer id;
#ManyToOne
#JoinColumn
private Office office;
etc...
}
So basically I'm wondering if this is the right way to be doing this. It is convenient to simply inject the collectionWrapper into my controllers and views, but I'm not sure how efficient it is on a lower level or if I'm missing something fundamental.
Thanks for sharing your experience!

Entity to Model and foreign key objects

I have an EF object called SportDivision. For simplicity's sake, I won't include every field, just the ones that are relevant:
[Table("SportDivision", Schema = "dbo")]
public class SportDivision: BaseReferenceEntity
{
public int Id { get; set; }
public string Name { get; set; }
public int SportId { get; set; }
[ForeignKey("SportId")]
public virtual Sport Sport { get; set; }
}
So it has a SportId and it's a foreign key that points to the table Sport.
Now, I can't just use an EF object in my views, so I have a model class that's mapped to SportDivision called SportDivisionModel:
public class SportDivisionModel: BaseReferenceModel
{
public int Id { get; set; }
public string Name { get; set; }
public int SportId { get; set; }
//Read only fields
public string Sport { get; set; }
}
I use automapper to transfer data from SportDivision to SportDivisionModel and vice versa. The mapping looks like this:
Mapper.CreateMap<SportDivision, SportDivisionModel>()
.ForMember(x => x.Sport, c => c.MapFrom(e => e.Sport.Name));
Mapper.CreateMap<SportDivisionModel, SportDivision>();
And I have a genericized service that CRUDs and translates data from entity to model or model to entity. Everything works fine except on Create, of which the function is shown below:
public TModel Create<TModel, TEntity>(TModel entry)
where TModel : BaseReferenceModel
where TEntity : BaseReferenceEntity
{
var dm = ServiceLocator.Current.GetInstance<ICrudService<TEntity>>();
var raw = Mapper.Map<TModel, TEntity>(entry);
var created = dm.CreateOrUpdate(raw);
return Mapper.Map<TEntity, TModel>(dm.FindById(created.Id));
}
In the very last line, where you see dm.FindById(created.Id), it returns a SportDivisionModel object with no Sport name. A null reference exception is found in .ForMember(x => x.Sport, c => c.MapFrom(e => e.Sport.Name));. It didn't load Sport after the entry was just created in the database.
I've debugged the code, and I see that the entry with a valid SportId is entered into the SportDivision table of my database, but when I try and bring it over to my MVC application, it doesn't get all the information.
This only is an issue on create. If I simply get data from the database without creating it beforehand, or if I edit the information, then the Sport field in my model object does get populated. I don't know why this is happening, and I can't use the .Include in my generic service call (because not all BaseReferenceEntity classes have a foreign key pointing to Sport).
Please advise. Thanks in advance.
I must play Sherlock Holmes and try to derive what could be the content of CreateOrUpdate and FindById from the indications in your question:
You say that you don't use Include because of the generic service. I assume that you also don't use explicit loading (Load) because you would face the same problem that you cannot really make it generic.
Conclusion: Because the Sport navigation property in the SportDivision gets loaded in certain scenarios (Edit) this can only happen due to lazy loading. The conclusion is backed by the fact that the Sport property is marked as virtual.
Lazy loading relies on proxies. If your SportDivision entity is a proxy then
either loading the Sport entity works
or you get an exception telling you that the context is already disposed (if you have disposed the context)
Number 2 is not the case -> Conclusion: Number 1 must be the case if the pre-condition is fulfilled
But Number 1 also isn't the case (loading Sport does not work)
Conclusion: The pre-condition that your SportDivision entity is a proxy is not true.
So: SportDivision is not a proxy. Could this mean that you have lazy loading in the context disabled? No: Because you are saying that editing works it means that when you load entities from the database they are loaded as proxies and support lazy loading.
Editing works, lazy loading isn't disabled but creating a new entity does not work in the way that the Sport entity is loaded when you proceed to use the newly created entity.
Conclusion: Your newly created entity (returned from CreateOrUpdate) is not a proxy and CreateOrUpdate looks similar to this:
public TEntity CreateOrUpdate(TEntity raw) where TEntity : class
{
if (blabla)
; //update
else
{
context.Set<TEntity>().Add(raw);
context.SaveChanges();
return raw;
}
}
and FindById is just:
public TEntity FindById(int id)
{
return context.Set<TEntity>().Find(id);
}
Since you are passing raw directly into the Add method of the DbSet<T> the question raises where does raw come from and how is it created.
Obviously AutoMapper creates the entity after this line: var raw = Mapper.Map<TModel, TEntity>(entry);
How does Automapper create an entity? Probably by calling new TEntity or by using some reflection code like Activator.CreateInstance or...
It doesn't really matter how, but for sure AutoMapper doesn't instantiate an Entity Framework proxy which had to be created by:
var entity = context.Set<TEntity>().Create();
If all this is true, I feel totally screwed by AutoMapper and generic excesses. If all this wouldn't be generic we could solve the problem by:
context.Set<SportDivision>().Add(raw);
context.SaveChanges();
context.Entry(raw).Reference(r => r.Sport).Load();
Instead we must try some ugly tricks now:
context.Set<TEntity>().Add(raw);
context.SaveChanges();
context.Entry(raw).State = EntityState.Detached;
// We hope that raw is now really out of the context
raw = context.Set<TEntity>().Find(raw.Id);
// raw must be materialized as a new object -> Hurray! We have a proxy!
return raw;
(I'm really not sure if the Detached trick above does work. Aside from that you are forced to reload an entity from the database you just have created and saved which is stupid somehow.)
Potential trick number 2 (without reloading from DB but for the price of being a further step more ugly):
context.Set<TEntity>().Add(raw);
context.SaveChanges();
context.Entry(raw).State = EntityState.Detached;
// We hope that raw is now really out of the context
var anotherRaw = context.Set<TEntity>().Create(); // Proxy!
anotherRaw.Id = raw.Id;
context.Set<TEntity>().Attach(anotherRaw);
context.Entry(anotherRaw).CurrentValues.SetValues(raw);
context.Entry(anotherRaw).State = EntityState.Unchanged;
return anotherRaw; // Proxy! Lazy loading will work!
Does AutoMapper have a feature of a "custom allocator or instantiator" and can custom user data (a context) be supplied? Then there would be a chance to let AutoMapper call context.Set<TEntity>().Create();. Or is it possible to instantiate the object by hand, pass it to AutoMapper and AutoMapper just updates the object's properties?
BTW: The line...
context.Entry(anotherRaw).CurrentValues.SetValues(raw);
...is kind of EF's built-in "AutoMapper". The parameter of SetValues is a general System.Object (could be your ...Model object) and the method maps property values from the supplied object to properties of attached entities by identical property names. Maybe you can leverage this feature somehow instead of using the mapping from model to entity done by AutoMapper.

Resources