C
C#10mo ago
Pibbles

Unit Testing Classes with Dependency Injection (ASP.NET Core)

How do you guys usually handle this? I saw some people mock every single injection which seems pretty horrible, other people end up in a way where they effectively have to rebuild the Program.cs class in their test project. I'm using xUnit To be a little more clear. The class I want to test on takes in some interfaces via dependency injection in it's constructor, and these are used in the methods I want to test. - Ideally, I want them to function how they actually would, using the concerete classes injected
33 Replies
Pobiega
Pobiega10mo ago
If you want to use the real implementations, then do that.
Pibbles
Pibbles10mo ago
Do what? Rebuild Prpgram.cs?
Pobiega
Pobiega10mo ago
no, use teh real implementations you could assemble a serviceprovider based on the real one from program if you want, or you just do var sut = new Sut(new dep1, new dep2) etc if thats feasible it all depends on your setup and how complicated your dependency graph is the reason mocking all dependencies is common is because * its easy * it makes your tests true unit tests (testing a distinct "unit" of code)
Pibbles
Pibbles10mo ago
Well those interfaces, the real implementation might also take some interfaces. And if I swap the concrete class I’m using for something I don’t want to have to go through every unit test and change it manually. As far as mocking each interface, I’d be okay with it, but then if I change the way that method works I’m again having to go to each unit test and change it And one of the interfaces is a mapper, so any change to the object I’m mapping and I’ll have to change them all etc
Pobiega
Pobiega10mo ago
Well those interfaces, the real implementation might also take some interfaces
Sure, so use dependency injection to resolve your service under test?
Pibbles
Pibbles10mo ago
Yeah I was just checking there wasn’t some simpler way people used but it seems like this is still the best
Pobiega
Pobiega10mo ago
honestly if you want to test like this (which is perfectly fine btw), I'd consider using WebApplicationFactory and TestingContainers (for a database or similar) and making full on integration tests why stop half the way there 🙂
Pibbles
Pibbles10mo ago
I mean, these should just be unit tests
Pobiega
Pobiega10mo ago
they are not if you are testing a service that has real dependencies that do actual work, thats no longer a unit by most definitions "Half my codebase is one unit" is a weird border if a single test "tests" a huge portion of your app, thats really close to a full E2E or integration test already
Pibbles
Pibbles10mo ago
I mean I would mock them if it weren't such a pain to do so but I'd say that if it's still internal to the project, and not using the more external stuff like a database, I'd still think of it as a unit test
Pobiega
Pobiega10mo ago
these are just terms for distinction btw, you can still use xUnit to make e2e or integration tests
Pibbles
Pibbles10mo ago
it's not using a huge portion at all it's basically using a helper method it's using a mapper
Pobiega
Pobiega10mo ago
right
Pibbles
Pibbles10mo ago
it's just that mocking the mapper is probably going to cause more pain down the line if I change the mapper or the object coming out hm maybe I should just mock it anyway
Pobiega
Pobiega10mo ago
mocking a mapper does indeed sound painful Then again
Pibbles
Pibbles10mo ago
it would make it more of a unit test you are right there, since rn it would effectively be testing the mapper
Pobiega
Pobiega10mo ago
I very rarely if ever use mappers in a service I prefer to do that at the endpoint level the service/command/etc is part of the domain, so it operates on domain objects your opinion might vary, and thats fine too 🙂
Pibbles
Pibbles10mo ago
oh I'm probably just naming stuff wrong tbh
Pobiega
Pobiega10mo ago
I don't think you are but perhaps 🙂
Pibbles
Pibbles10mo ago
I have the API, which is made up of the controller method -> service layer (handles business logic and calls mapper service) -> data access layer (contains no business logic)
Pobiega
Pobiega10mo ago
thats exactly what I assumed yes I don't do mapping in the service layer its not a service concern, imho its an API concern I could see a world where you reuse your domain/data/service layers for lets say a console app, and you want a different shape on the resulting data
Pibbles
Pibbles10mo ago
would you not test your controller method though?
Pobiega
Pobiega10mo ago
not via a unit test integration test, maybe but since my controllers are literally just "model bind a http request, issue a command based on that data, map result, return result" its not really a huge consideration every single command (or service, in your case) is ofc tested
Pibbles
Pibbles10mo ago
yeah mine is that without the mapping lmao
Pobiega
Pobiega10mo ago
and I usually have tests for my mappers too, if they are not trivial not to mention, Im leaning more and more towards static mapping methods these days
Pibbles
Pibbles10mo ago
hm, okay for now I think I'll mock the mapper, in reality I won't end up changing stuff a huge amount for it to be a pain, and I really don't like the idea of not mocking it, and then this unit test testing other units...you've convinced me
Pobiega
Pobiega10mo ago
AutoMapper etc is just more problem than its worth to me 🙂
Pibbles
Pibbles10mo ago
I made my own static mapper so yeah
Pobiega
Pobiega10mo ago
nice you know what you could do? idk how you currently build your services, but its somewhat common to have a "ConfigureServices" method that just takes an IServiceCollection in and works on that when that method is done, its still a servicecollection, aka mutable so you could use the real DI setup, modify the bits you need (change what mapper you use, or change the database connection etc) then build a provider for tests then use that provider to resolve your services/dependencies for testing, often done by a "fixture" in most test frameworks
Pibbles
Pibbles10mo ago
honestly man I'm going to mock it you totally convinced me when you pointed out that just using the service means I'd be testing the mapper method when testing this method if I have a unit test for this method I just want it testing this method
Pobiega
Pobiega10mo ago
Go for it, see how it feels
Pibbles
Pibbles10mo ago
well thanks again, talking it through really helped a lot
Pobiega
Pobiega10mo ago
👍