Unit Testing, AcionResult Metadata Properties and JsonSerializer.Deserialize [Answered]
Hi all, I'm trying to add Unit Test to my WebAPI. I choose to call my endpoints with an httpclient and make my asserts on deserialized response.
Now, it'm almost my first Unit Test experience so I don't know if I'm right or not so my first question is. Should it is an approach?
After that, when I try to deserialize my reponse, all content contains metadata properties that, in Array cases, change completely the type of property (object with { "$id": "1", "$values": [<the-array>]), so deserialize not work if I specify the response type. Is there a way to avoid/ignore metadata properties and just return my plain model?
Now I'm trying to remove them through Regex Replace but (and here it is the third question), Regex found correctly my pattern with groups, I try to return Group[1].Value from my MatchEvaluator but Regex.Replace return exactly the input variable, without changes, any help?
Thank you in advance
60 Replies
If you could show some code, this would be much easier. Can you show the controller, your tests, and perhaps some of your response models?
ok just a minute
this is my controller method
$code
To post C# code type the following:
```cs
// code here
```
Get an example by typing
$codegif
in chat
If your code is too long, post it to: https://paste.mod.gg/okay, and what does
UserGet
look like? any custom mapping going on or just normal stuff?Unit Test
hm, I don't see any WAF or similar here, where do you start the API?
Models
what is
httpHelper
?I've a BaseTest Unit with all theese things, dbContext, playgroundApplication and so on
httpHelper is a custom class I made
well its hard to help you troubleshoot things when you are not showing where the stuff is happening 😛
http helper seems to be making the actual HTTP requests, so we need to see that
ahahah sorry, I'm writing it now
and perhaps show the raw response you get for the user endpoint?
the raw response it a HttpMessageResponse
the content red as string is that
{"$id":"1","UserId":2219,"NameSurname":"Namebd2547c4-879c-44b3-927a-5a5d19262187","Email":"Mailc5643a9a-74be-4395-add7-9cce004a68b4","IsActive":true,"UserTenantRoles":{"$id":"2","$values":[{"$id":"3","UserId":2219,"UserMail":"Mailc5643a9a-74be-4395-add7-9cce004a68b4","UserName":"Namebd2547c4-879c-44b3-927a-5a5d19262187","TenantId":2727,"TenantGuid":"92298313-27aa-437f-a454-6539be1699de","TenantName":"Name3c1cb7af-9050-489e-ae60-c224e260adf2","RoleID":1,"RoleName":"Admin","AccessControlList":{"$id":"4","$values":[{"$id":"5","Id":9,"RoleId":1,"RoleName":"Admin","EntityScopeId":1,"EntityScopeName":"Tenants","CanRead":true,"CanWrite":true},{"$id":"6","Id":10,"RoleId":1,"RoleName":"Admin","EntityScopeId":6,"EntityScopeName":"Updates","CanRead":true,"CanWrite":true},{"$id":"7","Id":11,"RoleId":1,"RoleName":"Admin","EntityScopeId":3,"EntityScopeName":"Tvs","CanRead":true,"CanWrite":true},{"$id":"8","Id":12,"RoleId":1,"RoleName":"Admin","EntityScopeId":2,"EntityScopeName":"Users","CanRead":true,"CanWrite":true},{"$id":"9","Id":13,"RoleId":1,"RoleName":"Admin","EntityScopeId":4,"EntityScopeName":"Media","CanRead":true,"CanWrite":true},{"$id":"10","Id":14,"RoleId":1,"RoleName":"Admin","EntityScopeId":5,"EntityScopeName":"Pages","CanRead":true,"CanWrite":true}]}}]}}
yeah but if you extract the string body
yeah
(sorry, I'm a little slow to copy and paste)
and if you visit this endpoint with a normal browser, do you get the same json?
or is the metadata only showing during tests?
yes
I've tried with postman
yes to what 🙂
and I can see metadata properties
and also calling API from frontend have theese properties
ah okay, sounds like there is a problem with the mapping then
is that AutoMapper?
yep
(i'm looking for its config)
hm, thats weird
given that model, there shouldn't be any metadata
unless something funny is going on with the
this.Ok
Normally, you would type the controller action
ie public ActionResult Get()
would be
and just return the value directly, instead of manually wrapping it in an OK
exceptions will automatically become a Problem, by the default http pipeline
I gotta run, but will be back in ~30-60ok, thank you
so I've to change my Controller like that
HttpClientHelper.cs
I've tried to change returned type according with your suggestion but still get the same response
Back. Okay, so I find it weird that your response contains the
$id
property regardless of what you domaybe Automapper config?
and we'll need to figure that out before moving on to testing
Potentially. Do you have any automapper profiles loaded?
yep
okay, show me?
actually, a faster way to rule that out is
comment out the mapping, and just do
return new UserGet();
maybe give it some values
where backend data model user is the EF model
right
UserGet is the "outer" model
this is all fine, not the source
yeah the DTO
yep
actually, my current line of thinking is that this is because of a bad-configured json serializer in ASP
what .NET/ASP version are you using?
Net 6
okay
do you configure the json serializer at all?
should be in your startup.cs file, most likely
i'm looking in my program.cs and so on
can you show that file? just make sure it doesnt contain any connectionstrings or tokens
builder.Services
.AddControllers(options => {
options.Filters.Add<AclActionFilter>();
})
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
this is in my program.cs
alright, here we go
it there a way to use the shortcut to highlight the code?
wdym?
modix suggested me before but I've to search it in chat every time ^^
just type three backticks: ```cs <your code here> ```
I've italian layout and no backticks in my keyboard
oh. and a newline after the
cs
Im sure its there somewhere. On mine, its shift + the key left of backspace.
(swedish layout)
turns out there might not be, lol
https://superuser.com/questions/667622/italian-keyboard-entering-tilde-and-backtick-characters-without-changinyeah, Alt 96, thank you
you can edit your keyboard layout btw
so you could add it 🙂
I'll try to add next time
its useful in progrmaming
okay
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
its this line
that adds the $id fieldyou should avoid having cyclic references in general
its really bad practice :p
ok, I'll try to remove it but if I remember right, I added it to resolve other issues
I'm trying to remove them but in some cases they return...
well, since you are using DTOs
you should be mapping them away
example:
this makes sense at a C# level
but for json, if you tried serializing this you'd get a forever nested structure, as json doesnt support references (natively)
instead, you'd probably rely on Ids, or jsut the structure itself
if a pet can only have one owner, we can list them as an array under the person
essentially just removing the
Owner
prop from the pet, when serializing
thats a great usecase for a DTO
EF navigation properties will often lead to this result
which is why its important to map them to DTOs before returningYep, but in some case I had nested objects to avoid too much call from frontend and sometime it creates a loop
I inherit the backend from old developer and trying to fix many things
maybe this is the right time I resolve also this ^^
absolutely yes 😛
yep, I'll confirm that removing ReferenceHandler resolve this issue
thank you for your help and for your patience
✅ This post has been marked as answered!