Alllow Generate JsonNode/Proxy of Faker<T>
- Dominant language
- C#
- Stars
- 9.7k
- Forks
- 538
- PR merge metrics
- No merged PRs in 30d
Description
The typed Faker class is great to create complex builder scenarios, the power of defining the shape of the type in parts as necessary is one of the best things to solve problems like test scenarios.
Something like this:
```cs
public class User
{
public string Name { get; init; }
public int Age { get; init; }
public string Email { get; init; }
}
var builder = new Faker()
.RuleFor(x => x.Email, f => f.Person.Email)
.RuleFor(x => x.Age, f => f.Random.Int(18, 50))
.RuleFor(x => x.Name, f => f.Person.FirstName);
```
Things get a bit complicated when the Type has a complex constructor or a mix with required properties:
```cs
var builder = new Faker()
.RuleFor(x => x.Age, f => f.Random.Int(18, 50))
.RuleFor(x => x.Name, f => f.Person.FirstName)
.CustomInstantiator(f =>
new User(f.Person.Email)
{
Name = // need to be set //,
Age = // need to be set //,
});
```
In this case, we kinda lost the power of member composability. If it was a custom builder I would have to create fields to hold values for the `CustomInstantiator` etc.
So would be nice to have a way to get the shape of the data without constructing the actual Type
A generic way to solve this could be to have a new method like `GetJsonObject`, which for the case above could be something like:
```cs
var builder = new Faker()
.RuleFor(x => x.Email, f => f.Person.Email)
.RuleFor(x => x.Age, f => f.Random.Int(18, 50))
.RuleFor(x => x.Name, f => f.Person.FirstName);
var values = builde.GenerateJsonNode();
/*
new JsonObject
{
["Name"] = "Casey",
["Age"] = 22,
["Email"] = "Casey_Ebert22@hotmail.com",
};
*/
```
So it could be used on the complex constructor, preserving the member composability:
```cs
var builder = new Faker()
.RuleFor(x => x.Email, f => f.Person.Email)
.RuleFor(x => x.Age, f => f.Random.Int(18, 50))
.RuleFor(x => x.Name, f => f.Person.FirstName)
.CustomInstantiator(f => {
var values = f.GetJsonObject();
return new User((values["Email"].GetValue())
{
Name = values["Name"].GetValue(),
Age = values["Age"].GetValue(),
});
}
```
Another solution would be use [Castle](https://github.com/castleproject/Core) `DynamicProxy` to maintain the type contract but `mocking` the property values:
```cs
var builder = new Faker()
.RuleFor(x => x.Email, f => f.Person.Email)
.RuleFor(x => x.Age, f => f.Random.Int(18, 50))
.RuleFor(x => x.Name, f => f.Person.FirstName)
.CustomInstantiator(f => {
var proxy= f.GetObjectProxy();
return new User(proxy.Email)
{
Name = proxy.Name,
Age = proxy.Age
});
}
```
* Is the feature something that currently cannot be done?
I don't think so
* What alternatives have you considered?
Customize the Faker inheriting from it, or just create/initialize all the properties manually
* Is this feature request any issues or current problems? No
* Has the feature been requested in the past? No
**If the feature request is approved, would you be willing to submit a PR?**
*Yes*
Contributor guide
Research direction
The issue centers on Faker and CustomInstantiator; first review how those entry points currently compose member rules and construct values. Compare the proposed GenerateJsonNode and Castle DynamicProxy directions, then define the supported API and tests needed to show composed values are available without constructing User.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100