{"id":230,"date":"2021-02-02T20:03:11","date_gmt":"2021-02-02T20:03:11","guid":{"rendered":"https:\/\/fde.cat\/?p=230"},"modified":"2021-02-02T20:03:13","modified_gmt":"2021-02-02T20:03:13","slug":"simplify-testing-with-the-singleton-pattern","status":"publish","type":"post","link":"https:\/\/fde.cat\/index.php\/2021\/02\/02\/simplify-testing-with-the-singleton-pattern\/","title":{"rendered":"Simplify Testing With the Singleton Pattern"},"content":{"rendered":"<p>While you may be familiar with the technical offerings of Salesforce.com, you might not know much about <a href=\"https:\/\/www.salesforce.org\/about-us\/\">Salesforce.org<\/a>, the social impact center at Salesforce. We build solutions that utilize the Salesforce Platform, working to empower organizations in the non-profit and education sectors to achieve their missions by unlocking the power of Salesforce CRM.<\/p>\n<p>We\u2019re also the largest Salesforce ISV (independent software vendor; though not quite as independent as we <a href=\"https:\/\/www.salesforce.com\/news\/press-releases\/2019\/04\/15\/salesforce-and-salesforce-org-combine-to-drive-greater-philanthropic-impact-and-success-for-social-good-organizations\/\">used to be<\/a>!). We ship profiles, packages, and permission sets (not to mention lots and lots of Apex!). We strive to work on the cutting edge of the Salesforce platform, working with the latest releases of <a href=\"https:\/\/lwc.dev\/\">Lightning Web Components<\/a> and Apex improvements available to us. Salesforce developers don\u2019t showcase design patterns as much as developers in other ecosystems do, but we work with them all the time at Salesforce.org. I\u2019d like to talk about one of my team\u2019s favorite patterns\u00a0today.<\/p>\n<figure><img decoding=\"async\" alt=\"\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1000\/1*Z73Mha6ocKDNLN57Yi1hZA.png?w=750&#038;ssl=1\" data-recalc-dims=\"1\"><\/figure>\n<p><strong>Who is this\u00a0for?<\/strong><\/p>\n<p>If you hold a traditional computer science degree, you\u2019re probably well-versed in design patterns and can skip ahead to the nitty-gritty technical details. However, Apex developers aren\u2019t always traditional engineers; plenty of successful developers I know in the Salesforce ecosystem began their coding journey as Salesforce administrators and have picked up development skills in Apex; others have skipped the four-year degree entirely!<\/p>\n<p>I\u2019m also a non-traditional, self-taught developer. I got my technical bonafides through a development bootcamp. The course that I took alluded to the existence of design patterns, but our instructors told us that we wouldn\u2019t have to worry about that until much later in our careers (and they were right!). I\u2019m several years in as a developer now, and I can tell you that design patterns have a place in all modern coding languages, including Apex. (Examples will be provided in Apex, but the principles can apply to other OOP languages.)<\/p>\n<p><strong>So what are design patterns?<\/strong><\/p>\n<p><em>A design pattern is a reusable form of a solution to a design\u00a0problem.<\/em><\/p>\n<p>But what does that mean,\u00a0exactly?<\/p>\n<p>That\u2019s a fancy way of saying that a pattern is a familiar way of solving well-known problems quickly. They can create shared understanding without digging into technical details, and their benefits and drawbacks can be found in numerous books and articles on patterns.<\/p>\n<p>However, patterns can be difficult to maintain and can become more rigid than a simpler solution would have been. If you don\u2019t recognize the pattern (and there are lots of patterns out there!), you can create unnecessary complexity and confusion amongst the\u00a0team.<\/p>\n<p>For example, if we\u2019re all going out to eat and I say \u201cLet\u2019s go get pizza!,\u201d that\u2019s a lot faster and easier than saying \u201cLet\u2019s go get that wheat-based, cheese and red-sauce covered baked food! You know, the round\u00a0one!\u00b2\u201d<\/p>\n<p>But if I say \u201cLet\u2019s go get penne alla vodka!\u201d, not everyone is going to know what I\u2019m talking about. Some of you might think we\u2019re going out for drinks, others might think I don\u2019t know good Italian food, and some of y\u2019all might be excited that we\u2019re going out for this super specific and tasty pasta dish. It would just be easier to say \u201clet\u2019s go for pasta\u201d, and we\u2019ll figure out the rest when we get\u00a0there.<\/p>\n<p>In the words of Erich Gamma, one of the authors of the original <a href=\"https:\/\/en.wikipedia.org\/wiki\/Design_Patterns\"><em>Design Patterns: Elements of Reusable Object-Oriented Software<\/em><\/a> (aka the <a href=\"http:\/\/wiki.c2.com\/?GangOfFour\">Gang of Four<\/a>): \u201cA design pattern should only be applied when the flexibility it affords is actually needed.\u201d Before we consider using a design pattern, we should be sure that it fits our needs, and that everyone who will be working with it understands it\u00a0well.<\/p>\n<p><strong>Singleton Pattern<\/strong><\/p>\n<p>One pattern that I work with every day is the Singleton Pattern. It\u2019s known as one of the foundational patterns, since it was defined in the original <em>Design Patterns<\/em> book. The Singleton is a creational pattern, which means that it\u2019s used to define the creation of\u00a0objects.<\/p>\n<p><em>The Singleton pattern ensures that only one instance of a class exists and there is a global point of access to\u00a0it.<\/em><\/p>\n<p>Clear as mud right? Let\u2019s break it\u00a0down.<\/p>\n<figure><img decoding=\"async\" alt=\"A singular line of railroad track that splits into two paths after the dividing railroad switch\" src=\"https:\/\/cdn-images-1.medium.com\/max\/409\/0*QHTozS41hHEHbjwL\"><figcaption>Image credit: <a href=\"https:\/\/en.wikipedia.org\/wiki\/Railroad_switch\">Wikipedia<\/a><\/figcaption><\/figure>\n<p><strong>Singleton as a Railroad\u00a0Switch<\/strong><\/p>\n<p>I like to think of the Singleton as a railroad\u00a0switch.<\/p>\n<p>A switch is what determines which direction a train will go when it reaches a possible alternative path. The normal path will allow the train to continue straight ahead. If the switch is pulled, then the train will take the other path. The tracks and the train only respond to what the switch tells them to\u00a0do!<\/p>\n<p>Let\u2019s add apply this to a simple\u00a0model:<\/p>\n<figure><img decoding=\"async\" alt=\"Visual code diagram: the client calls getInstance, which calls the First Class, which calls the Second Class, and so on.\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/0*OqUuustvALoXSRYB\"><figcaption>Example A: Simple Model, where the switch isn\u2019t\u00a0pulled<\/figcaption><\/figure>\n<p>Here we have a controller class, which in Apex would be called by an Aura or Lightning Web Component client. The controller calls the instance of the \u201cFirst Class\u201d, which is where our Singleton Pattern is used (we\u2019ll see how to set that up down below!). Execution continues to a second class, and possibly further down the line until it finishes its\u00a0job.<\/p>\n<figure><img decoding=\"async\" alt=\"The same image as image A, but getInstance redirects to a Stubbed Class instead of First Class.\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/0*G3Jh5M34tE3Zwblc\"><figcaption>Example B: Simple Model, the switch IS\u00a0pulled<\/figcaption><\/figure>\n<p>When the switch is pulled (Example B), our code flow will be diverted into the Stubbed class. Think of that alternate path in the photo above; the journey ends here where the Stub lets you arrive early to the\u00a0station!<\/p>\n<p><strong>So what does this all have to do with\u00a0testing?<\/strong><\/p>\n<p>We\u2019ve covered the basic mechanics of the Singleton pattern, but why should we use it? Isn\u2019t this just making our code more verbose and confusing? And what does all of this have to do with testing\u00a0anyway?!<\/p>\n<p>As Erich tells us, we should only apply patterns when we really need them, not just because some writer on the internet tells you to use\u00a0it.<\/p>\n<p>In the case of testing, here are some problems we may encounter:<\/p>\n<ol>\n<li>Our classes and their dependencies can get very complex, and we don\u2019t want to do end-to-end testing for every class, especially controllers.<\/li>\n<li>We can\u2019t always test at specific dates or times. What about bugs that happen only on the last day of the month, or 11:59PM\u00a0GMT?<\/li>\n<li>We can\u2019t (or don\u2019t want to) create specific data, such as custom settings, objects, or permissions.<\/li>\n<\/ol>\n<p><strong>How do we solve these problems with this\u00a0pattern?<\/strong><\/p>\n<p>Stub it\u00a0out!<\/p>\n<p>The Singleton pattern allows us to stub out the data we\u2019re expecting, and test one method at a time (as a good test should). We can return \u201cdata\u201d from downstream methods that we haven\u2019t actually inserted, or specific dates and\u00a0times.<\/p>\n<p>For those of you intimately familiar with Apex development, this all might seem eerily similar to the Stub API\u200a\u2014\u200aand it is! However, this is a fully customizable solution that allows you to stub out everything that you want without worrying about platform limitations.<\/p>\n<p><strong>Building a\u00a0Switch<\/strong><\/p>\n<p>So first off, there\u2019s a lot of code coming your way! If you\u2019re not a coder, no worries! We\u2019ll keep our railroad switch example in mind, and I\u2019ll show you where the payoff is at the end. With that, let\u2019s look at some code and get to stubbing it\u00a0out!<\/p>\n<figure><img decoding=\"async\" alt=\"Code block that will be described below.\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/0*1Wo6hLYRk9JVvMGo\"><figcaption>Example C: Class using the Singleton pattern (gist\u00a0<a href=\"https:\/\/gist.github.com\/randi274\/50558ca02cbf6c89acecfbe21f602204\">here<\/a>).<\/figcaption><\/figure>\n<p>This is a class that returns the current date and time as a single piece of data. We apply the Singleton to the class in order to stub it out easily, and get any date we want using the now() method. Let\u2019s see how that\u00a0happens:<\/p>\n<ol>\n<li>To start, we apply the virtual modifier to the class, which allows us to extend the class and override\u00a0methods.<\/li>\n<li>Create a private instance variable that\u2019ll be visible to tests only. This is what holds that current instance in\u00a0memory.<\/li>\n<li>This is the railroad switch! Create a public method to get the instance. If no instance is provided, then we continue on straight with our normal path. If another instance has been created (which could also be this one, the code that\u2019s being executed doesn\u2019t know or care!), then use that\u00a0instead.<\/li>\n<li>Protect the constructor so we can subclass it for tests, but not access it directly during normal runtime (only through the getInstance method).<\/li>\n<li>Finally\u200a\u2014\u200aoverride any methods we want, and stub out the data that we\u2019re expecting.<\/li>\n<\/ol>\n<p><a href=\"https:\/\/medium.com\/media\/b63eda0c3010415ba342afc4ddaf1742\/href\">https:\/\/medium.com\/media\/b63eda0c3010415ba342afc4ddaf1742\/href<\/a><\/p>\n<p>Think back to our data model\u200a\u2014\u200athis is where the Apex code flow starts. Here we get the instance of our DateTimeProvider, which will tell us which direction we\u2019re going when the code runs. Again, we\u2019re forced to stay on track with the use of the getInstance method rather than creating a new instance of the class because the DateTimeProvider\u2019s constructor isn\u2019t\u00a0public.<\/p>\n<p>One scenario where we often need to run extra tests is during a leap year! This method will simply use the now() method to determine if it\u2019s a leap year, and will print out a different message depending on if it is a leap\u00a0year.<\/p>\n<figure><img decoding=\"async\" alt=\"Singleton Test code, collapsed. Highlighting two test methods, testLeapYear and testNonLeapYear. Shows the stub DateTimeStub.\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/0*ZcHVQC7cWN8ItWTs\"><figcaption>Example E: Adding the stub to the test (gist\u00a0<a href=\"https:\/\/gist.github.com\/randi274\/496254459945c16f28466b504ade1b45\">here<\/a>).<\/figcaption><\/figure>\n<p>This is where we set up our switch, or stub. We create a new private subclass for the DateTimeProvider instance directly in the test class. This extends the same capabilities as the DateTimeProvider, and also has a now() method. However, we can pass into our now() method whatever date we want! This will allow us to stub out the date that we\u2019re expecting, without us having to wait a whole year to get a different test\u00a0result.<\/p>\n<figure><img decoding=\"async\" alt=\"Singleton Test methods expanded. testLeapYear not stubbed out. testNonLeapYear stubs DateTimeProvider.\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/0*LnrNJak-GaWIPL4H\"><figcaption>Example F: Throwing the switch in the test (gist\u00a0<a href=\"https:\/\/gist.github.com\/randi274\/496254459945c16f28466b504ade1b45\">here<\/a>).<\/figcaption><\/figure>\n<p>Now the tracks have been laid out, and we\u2019re ready to get this train moving. We have two test methods to test both scenarios: in one, we\u2019re expecting it\u2019ll be a leap year, and in the other we\u2019re expecting that it won\u2019t\u00a0be.<\/p>\n<p>For our first test, we don\u2019t have to do anything because 2020 is a leap year! So we can continue on our straight path without pulling the\u00a0switch*.<\/p>\n<p><em>*Technical footnote\u200a\u2014\u200ain practice, you\u2019d want to stub out a set leap year regardless, even if you know that this year <\/em><strong><em>is<\/em><\/strong><em> a leap year. Next year (2021) won\u2019t be, so you don\u2019t want your tests to start failing on Jan\u00a01.<\/em><\/p>\n<p>In the second test, we\u2019re going to use our stub, and throw the switch. We create a set date (a day in 2019), which we pass into our stub to tell it what day we want to use. When we call printDateTime(), the controller will encounter the already existing DateTimeProvider instance (our stub), and will use that alternative path during execution. If we were doing more with this method, you would also expect to set up some assertions based on our stubbed out\u00a0data.<\/p>\n<figure><img decoding=\"async\" alt=\"Log outputs: \u2018Hey is it a leap year? Do we need extra testing?\u2019 Line break. \u2018Yep! Get testing!\u2019\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/0*gfeQ6WEq_BzfrAnP\"><figcaption>testLeapYear (2020)<\/figcaption><\/figure>\n<p>From our first test, we see that it is, in fact, a leap year, since 2020 is a leap\u00a0year!<\/p>\n<figure><img decoding=\"async\" alt=\"Log outputs: \u2018Hey is it a leap year? Do we need extra testing?\u2019 Line break. \u2018All Clear. Enjoy your free time\u00a0:) \u2019\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/0*dgr_nYBPmv_3Reff\"><figcaption>testNonLeapYear (2019)<\/figcaption><\/figure>\n<p>In our second test we used a date in 2019 as our version of \u201cnow\u201d, so the printed message agrees that we shouldn\u2019t expect any weirdness due to leap\u00a0years.<\/p>\n<p><strong>Final Thoughts<\/strong><\/p>\n<p>There are plenty of other reasons to use the Singleton pattern (for instance, my team will sometimes combine it with the Factory pattern when we create new features in order to give our users even more flexibility!).<\/p>\n<p>In this example, you could also provide lots of stubbed classes, and provide them in different combinations to test all of the different conditionals in your code. You can even overwrite the same instance in one test class, if you need\u00a0to.<\/p>\n<p>Hopefully this leaves you either feeling more confident about using design patterns in your own code, or excited to learn more about design patterns. If you\u2019re a developer looking to learn more about what we\u2019re working on (and take a peek at some of our open source code!), check out our Github repo <a href=\"https:\/\/github.com\/SalesforceFoundation\/\">here<\/a>. (And if you\u2019d like to learn more about <a href=\"https:\/\/www.salesforce.com\/company\/careers\/\">working with us<\/a> directly, we\u2019re frequently hiring\u00a0too!)<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/medium.com\/_\/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=1a53ba5c2c50\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<hr>\n<p><a href=\"https:\/\/engineering.salesforce.com\/simplify-testing-with-the-singleton-pattern-1a53ba5c2c50\">Simplify Testing With the Singleton Pattern<\/a> was originally published in <a href=\"https:\/\/engineering.salesforce.com\/\">Salesforce Engineering<\/a> on Medium, where people are continuing the conversation by highlighting and responding to this story.<\/p>\n<p><a href=\"https:\/\/engineering.salesforce.com\/simplify-testing-with-the-singleton-pattern-1a53ba5c2c50?source=rss----cfe1120185d3---4\" target=\"_blank\" rel=\"noopener\">Read More<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>While you may be familiar with the technical offerings of Salesforce.com, you might not know much about Salesforce.org, the social impact center at Salesforce. We build solutions that utilize the Salesforce Platform, working to empower organizations in the non-profit and education sectors to achieve their missions by unlocking the power of Salesforce CRM. We\u2019re also&hellip; <a class=\"more-link\" href=\"https:\/\/fde.cat\/index.php\/2021\/02\/02\/simplify-testing-with-the-singleton-pattern\/\">Continue reading <span class=\"screen-reader-text\">Simplify Testing With the Singleton Pattern<\/span><\/a><\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","footnotes":""},"categories":[7],"tags":[],"class_list":["post-230","post","type-post","status-publish","format-standard","hentry","category-technology","entry"],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":751,"url":"https:\/\/fde.cat\/index.php\/2023\/08\/22\/how-is-einstein-gpt-shaping-the-future-of-salesforce-development-and-unleashing-developer-productivity\/","url_meta":{"origin":230,"position":0},"title":"How is Einstein GPT Shaping the Future of Salesforce Development and Unleashing Developer Productivity?","date":"August 22, 2023","format":false,"excerpt":"By Yingbo Zhou and Scott Nyberg In our \u201cEngineering Energizers\u201d Q&A series, we examine the professional life experiences that have shaped Salesforce Engineering leaders. Meet Yingbo Zhou, a Senior Director of Research for Salesforce AI Research, where he leads the team to develop the model for Einstein GPT for Developers\u2026","rel":"","context":"In &quot;Technology&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":791,"url":"https:\/\/fde.cat\/index.php\/2023\/08\/22\/how-is-einstein-shaping-the-future-of-salesforce-development-and-unleashing-developer-productivity\/","url_meta":{"origin":230,"position":1},"title":"How is Einstein Shaping the Future of Salesforce Development and Unleashing Developer Productivity?","date":"August 22, 2023","format":false,"excerpt":"By Yingbo Zhou and Scott Nyberg In our \u201cEngineering Energizers\u201d Q&A series, we examine the professional life experiences that have shaped Salesforce Engineering leaders. Meet Yingbo Zhou, a Senior Director of Research for Salesforce AI Research, where he leads the team to develop the model for Einstein for Developers, a\u2026","rel":"","context":"In &quot;Technology&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":229,"url":"https:\/\/fde.cat\/index.php\/2021\/02\/02\/ml-lake-building-salesforces-data-platform-for-machine-learning\/","url_meta":{"origin":230,"position":2},"title":"ML Lake: Building Salesforce\u2019s Data Platform for Machine Learning","date":"February 2, 2021","format":false,"excerpt":"Salesforce uses machine learning to improve every aspect of its product suite. With the help of Salesforce Einstein, companies are improving productivity and accelerating key decision-making. Data is a critical component of all machine learning applications and Salesforce is no exception. In this post I will share some unique challenges\u2026","rel":"","context":"In &quot;Technology&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":544,"url":"https:\/\/fde.cat\/index.php\/2022\/02\/22\/the-unified-infrastructure-platform-behind-salesforce-hyperforce\/","url_meta":{"origin":230,"position":3},"title":"The Unified Infrastructure Platform Behind Salesforce Hyperforce","date":"February 22, 2022","format":false,"excerpt":"If you\u2019re paying attention to Salesforce technology at all, you\u2019ve no doubt heard about Hyperforce, our new approach to deploying Salesforce on public cloud providers. As with any big announcement, it can be a little hard to cut through the hyperbolic language and understand what\u2019s going\u00a0on. In this blog series,\u2026","rel":"","context":"In &quot;Technology&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":585,"url":"https:\/\/fde.cat\/index.php\/2022\/02\/22\/the-unified-infrastructure-platform-behind-salesforce-hyperforce-2\/","url_meta":{"origin":230,"position":4},"title":"The Unified Infrastructure Platform Behind Salesforce Hyperforce","date":"February 22, 2022","format":false,"excerpt":"If you\u2019re paying attention to Salesforce technology at all, you\u2019ve no doubt heard about\u00a0Hyperforce, our new approach to deploying Salesforce on public cloud providers. As with any big announcement, it can be a little hard to cut through the\u00a0hyperbolic language and understand what\u2019s going on. In this blog series, we\u2019ll\u2026","rel":"","context":"In &quot;Technology&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":696,"url":"https:\/\/fde.cat\/index.php\/2023\/04\/04\/video-meet-5-salesforce-engineers-who-are-innovating-the-future\/","url_meta":{"origin":230,"position":5},"title":"[video] Meet 5 Salesforce Engineers Who Are Innovating the Future","date":"April 4, 2023","format":false,"excerpt":"In our \u201cEngineering Energizers\u201d Q&A series, we examine the life experiences and career paths that have shaped Salesforce engineering leaders. This special edition connects five of the best and brightest minds within Salesforce Engineering and across the world including India, Argentina, and the U.S., chronicling their quest to innovate the\u2026","rel":"","context":"In &quot;Technology&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/posts\/230","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/comments?post=230"}],"version-history":[{"count":1,"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/posts\/230\/revisions"}],"predecessor-version":[{"id":245,"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/posts\/230\/revisions\/245"}],"wp:attachment":[{"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/media?parent=230"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/categories?post=230"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fde.cat\/index.php\/wp-json\/wp\/v2\/tags?post=230"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}