Whenever you write unit tests, the time comes that you have to mock data. Mocking this data can become tedious in many ways. Either the data gets c...
For further actions, you may consider blocking this person and/or reporting abuse
Looks clean. I will probably extend this to allow set multiple parameters at once, without unnecessary chain of
withespecially when you have bigger objects and need to set multiple object parameters:Lovely addition, thanks!!
Always use whatever works best for your use case. Another possibility is to add custom methods to the concrete builders. E.g., when the first name and last name are often set together on a
Person, then you could implement awithNamemethod in thePersonBuilder.Note: Do not forget to mark the
intermediateproperty asprotectedinside theBuilderclass when doing this.Using the
withNameinside your unit tests:Thanks for your input, much appreciated!
I usually forget the power of typescript. We are using the pattern in both backend and frontend.
Usually we combine it with Object mother to allow a different set of defaults (aMinimalPerson(), aConpletePerson()).
Also, it gets more complicated when having nested objects where each level has its own builder but you want to create a complete defaults object from the base builder but also want to modify a single value in the lead object.
We create something like
PersonBuilder.aFullPerson().modifyAddress().withZipCode(12345).done().build().
Here, modifyAddress return a builder filled with all the data from the main builder. Done() return back the parent builder.
This is quite complicated to implement in Java, I would really like to see if there is an elegant solution for this in Typescript.
I think it will become quite complex when you start mixing child/parent builders inside your chaining.
As suggested in my comment to @dikamilo, you could add custom methods to the
PersonBuilderthat provide several defaults (besides the actualsetDefaultsimplementation). An example:You can then create a person with your custom method and if you want to change the
petsproperty, just initialize one with thePetBuilderand use thewith.I think this is more "KISS" and will keep your code more readable as well.
Feel free to provide feedback!
As I mentioned before, we are heavily using builders for our test data for years and it is awesome.
Unfortunately, in reality data object are not that simple (as a person). We have heavily nested data structures, e.g.:
And both a, b and c represent own domain types with it's own builders and each object has lots of properties in reality.
We often ended up in a scenario that looks like this:
Actually,
ABuilder.anA().build()would already create all children as defaults, using builders as you did in your example. However, we need to change only the id of C in our test case. In reality, those objects are way more complex in our case and we end up having a lot of code in our test cases. To improve readability, we moved that code into helper functions.So we had builders to not repeat our selves and we had object mother function to create a valid object but in the end, we always had to customise code in every test case with seemingly unnecessary code.
That why we introduced that parent/child relation in the abstract builder. It's not pretty BUT we only had to do it once. Now we can write very elegant code that requires only the very necessary bits.
We are very happy with this but you might not need it for rather simple objects as in your example.
Nice and clean! Thanks for sharing it. π