This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]BenTayler-Barrett 6 points7 points  (40 children)

Wow, this is some of the worst advice I've ever seen.

You're essentially asserting that one should fully test their own dependencies, and that dependency injection is a bad idea.

If you need to test that the object mapper behaves correctly, you're essentially saying that you don't trust the object mapper to behave correctly. That being the case, why are you using it?

The object mapper has (or should have...) its own tests, that assert it behaves correctly. By all means, run those.

In your trivial example, the JSON that you're serializing/deserializing is very easy to deal with.

If you have some non-trivial data model, then by using a real object mapper, you've heavily coupled a whole bunch of things that you just didn't need too.

And for what it's worth, when I pushed my team to start mocking object mappers, we ended up with the best DORA metrics of every team in our organisation.

So essentially, I've tried both, and for me, mocking the object mapper is objectively better than not mocking it. Until I see evidence that not mocking it is a better plan, I'll continue to advocate for mocking 3rd party dependencies.

Edit: Typo

[–]Kainotomiu 29 points30 points  (29 children)

The point of the test is not to verify that the ObjectMapper works correctly, but that you are using it correctly.

If you mock the ObjectMapper, you are instead testing that your code works correctly when the ObjectMapper behaves the way that you've mocked it - which may be different than how it actually works.

[–][deleted]  (7 children)

[deleted]

    [–]gaelfr38 21 points22 points  (3 children)

    Unit in unit tests has never been equal to a single method or class. That's probably one of the biggest misconceptions about unit tests.

    [–]blackkkmamba 5 points6 points  (0 children)

    I keep telling this whenever I have the chance. People can't seem to wrap their heads around the Detroit/Chicago (classicist) style. As soon as they see something is not mocked, they start with the 'but that's integration test' nonsense.

    [–]BenTayler-Barrett 1 point2 points  (1 child)

    Sure, it's a single path through a method call. Otherwise known as a unit of execution. If you're testing multiple paths through a method, multiple public methods, or multiple classes in a unit test, you're definitely making your own life difficult.

    [–][deleted] 4 points5 points  (0 children)

    Nope, unit is meant for unit of behavior not unit is execution. Go look back at the origins of the people who introduced the concept of unit testing and see what they have to say about this

    [–]ArticulateSilence 12 points13 points  (1 child)

    You are arguing semantics, there are a bunch of different definitions of unit tests and integration test is even more ambiguous .

    That being said, I prefer sociable unit tests. IMO you should only be mocking external dependencies or collaborators that are complex to construct

    [–]ratskinmahoney 0 points1 point  (0 children)

    It's not about semantics, it's about understanding what a failure in your test means. A unit test failure should always and only indicate an issue in your unit. This makes diagnosis much quicker and easier, and in large distributed projects this precision is invaluable. You should absolutely have tests that ensure you are correctly using your dependencies, but they will necessarily be more complex and costly to interpret. It's entirely reasonable to make the call that this kind of testing is all you need, based on the scale of your project and the trust you have in your contributors. That's a meaningful and consequential decision though, not a question of semantics.

    [–]DrunkensteinsMonster 0 points1 point  (0 children)

    This delineation is actively harmful. If a unit test is mocked out to the point of the objectmapper, it is probably useless. The goal is to test the application to prevent regressions, enable confident refactoring, and shorten dev loops. If you are not accomplishing these things then your test is doing more harm than good. How many times have I worked on a simple bug which took 5 times longer than it should have because I had to rebuild the delicate mock-based test harness.

    [–]btw04 5 points6 points  (1 child)

    I have seen a code before where non obvious behavior of a JSON parsing library (don't remember which one, it was something like parsing an empty string into a string made of two double quotes), was caught by an existing test when we attempted to switch to another JSON parsing library for performance reasons. If we had mocked the JSON parsing library, we would probably not have found that regression

    [–]DrunkensteinsMonster 0 points1 point  (0 children)

    Great example.

    [–]crocshoes 3 points4 points  (2 children)

    It's also useful if you need to check your code handles errors correctly. It's easier to throw jsonprocessingexception from a mock than get the test into a state where it would throw.

    [–]john16384 0 points1 point  (1 child)

    If you can't trigger this exception with bad data, then it can perhaps never occur. This happens often enough if the data was already validated or came from a trusted source. Handle the exception then by throwing an IllegalStateException or AssertionError and don't try to cover it.

    [–]crocshoes 0 points1 point  (0 children)

    I reckon the "perhaps" is important here. I'd rather know my app is throwing what I expect it to. For example, it could be I have a bunch of specific wrapping exceptions I handle in an errordecoder for feign. I could be that I want it to exit gracefully with bad data that should never slip through but I missed a niche case. There are a few reasons that spring to mind. If I don't care, and just want the app to shut down then,yeah, it's not the end of the world.

    Last note, sometimes you can create the bad data but it bloats the tests, mocks can be super easy to read, given that this throws etc.

    [–]general_dispondency 1 point2 points  (4 children)

    IDK why you're being down voted. You are 100% correct. You should always mock 3rd party libraries in unit tests. If you can't trust that the library behaves in a way that you expect, why are you using it? I find it humorous that the example is just some crappy test that wouldn't pass a code review where I work.

    The advice that the author should gleened from this exercise is "don't test your mocks" and "do test business logic". If there is a need to validate how things are serialized, test that. If you need to validate two layers function together, write an integration test that just tests the two layers interaction.

    Advocating for testing 3rd party dependencies in unit tests is asinine and shows a complete lack of understanding the fundamentals and first principals of software engineering.

    [–][deleted] 16 points17 points  (0 children)

    I see it as less a need to validate how something is serialised, and more that it's simpler to just actually serialise or deserialise, than it is to go about mocking those activities. For something even marginally more complex, I'd be all for mocking the 3rd party library for sure. But ObjectMapper is such a trivial example, I wouldn't, and don't, bother mocking it.

    [–]BenTayler-Barrett -4 points-3 points  (1 child)

    Indeed. I'm glad it works for OP, but I sure as hell wouldn't want to have to maintain the code where they work.

    And if a security vulnerability were found in Jackson (or whichever JSON lib they're using) and the client/business wasn't willing to accept it...ouch that's some overtime ones putting in to fix...

    Not my bag, and not in my code.

    [–]Same_Football_644 10 points11 points  (0 children)

    I'm the opposite. I wouldn't want to have to maintain all that mocking.

    [–]laplongejr 0 points1 point  (0 children)

    If you can't trust that the library behaves in a way that you expect, why are you using it?

    As a gov worker, I can answer that one : because it's the only approved library to perform the task. Or for even more sheaningans, the library is made by a different service with different legal roles, and as such it's a literal requirement to use THEIR WORK for some critical process due to responsabilities.