{"id":5301,"date":"2021-06-23T12:02:43","date_gmt":"2021-06-23T16:02:43","guid":{"rendered":"https:\/\/xp123.com\/articles\/?p=5301"},"modified":"2021-11-13T21:36:13","modified_gmt":"2021-11-14T02:36:13","slug":"testing-objects-and-relationships","status":"publish","type":"post","link":"https:\/\/xp123.com\/testing-objects-and-relationships\/","title":{"rendered":"Testing Objects and Relationships"},"content":{"rendered":"\n<div class=\"convertkit-form\">\n\n\n<div class=\"convertkit-form wp-block-convertkit-form\" style=\"\"><script async data-uid=\"44f57802e4\" src=\"https:\/\/xp123.kit.com\/44f57802e4\/index.js\" data-jetpack-boost=\"ignore\" data-no-defer=\"1\" data-no-optimize=\"1\" nowprocket><\/script><\/div>\n\n\n\n<\/div>\n\n\n\n<p><br>When working with objects, there are different ways you can make them interact. We\u2019ll take a quick look at a variety of connections, what\u2019s needed to test them, and some alternatives you might consider.&nbsp;<\/p>\n\n\n\n<p>The connections below are in generally increasing order of complexity, but this is not a simple categorization &#8211; a class can use multiple approaches.<\/p>\n\n\n\n<p>I find it helpful to think of value objects as the simpler form. These are types are defined (and compared for equality) by their attributes, and includes types such as like money, position, names, \u2026&nbsp; As you get outside of value types, and into types that represent entities, you find they tend to collaborate more with other types.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Pure Function of Values<\/strong><\/h2>\n\n\n\n<p>A <em>pure function<\/em> produces deterministic outputs for a given set of inputs.&nbsp;<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/pure-fn.png\"><img loading=\"lazy\" decoding=\"async\" width=\"500\" height=\"55\" src=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/pure-fn.png\" alt=\"Pure function: input to outputs\" class=\"wp-image-5303\" srcset=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/pure-fn.png 500w, https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/pure-fn-300x33.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>This is the easiest to test: Create the object and its input values, and assess that the output matches the expected value.<\/p>\n\n\n\n<p>You might think this is a special case, but functional programming is typically this plus functions of functions.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>History of Interactions<\/strong><\/h2>\n\n\n\n<p>Some objects are driven by the history of prior calls. Container classes are a prime example of this. (See my articles on containers in the <a href=\"#references\">References<\/a>.) Containers are often generic classes, with minimal requirements on the contained object (perhaps Equatable or Hashable).&nbsp;<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/history.png\"><img loading=\"lazy\" decoding=\"async\" width=\"500\" height=\"160\" src=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/history.png\" alt=\"History of interactions: input to outputs and new state\" class=\"wp-image-5304\" srcset=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/history.png 500w, https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/history-300x96.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>These tests look like this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Create the object\nCall a series of mutator methods to set up a particular context\n\nCall the method whose behavior you\u2019re testing\n\nCall \u201cobserver\u201d methods to check the resulting state<\/pre>\n\n\n\n<p>Interestingly, this sort of object is one of the things that separate functional and object-oriented programming. Designing functional data types that are both immutable and efficient is a research challenge. (See Okasaki\u2019s book in the <a href=\"#references\">References<\/a>.)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Objects with Collaborators&nbsp;<\/strong><\/h2>\n\n\n\n<p>When an object collaborates with others, the collaborator could be established through a constructor or setter, or passed into a method. (It could also be a global; we\u2019ll look at that later.)<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/collab.png\"><img loading=\"lazy\" decoding=\"async\" width=\"500\" height=\"212\" src=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/collab.png\" alt=\"Collaborators: input to outputs, new state, and potentially new state of collaborators\" class=\"wp-image-5305\" srcset=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/collab.png 500w, https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/collab-300x127.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>For basic testing of this, there are two main approaches:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><em>Collaborate with the real object<\/em><\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">Set up collaborators\nCreate the object\n\nCall the method whose behavior you\u2019re testing\n\nCheck the result, on the tested object and\/or its collaborators<\/pre>\n\n\n\n<p>2. <em>Collaborate with test doubles (fake or mock)<\/em><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Set up collaborator test doubles\nCreate the object\n\nCall the method whose behavior you\u2019re testing\n\nCheck the result, on the tested object and\/or its collaborators (test doubles)<\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Fake vs Mock<\/strong><\/h3>\n\n\n\n<p>When the tested object uses collaborators to provide (or absorb) values, it is a good place for a simple fake object.<\/p>\n\n\n\n<p>In other cases, the behavior we\u2019re testing is the <em>pattern<\/em> of how the object interacts with its collaborator. In this case a mock is typically used to enforce that calls occur in the expected order.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Changing the Coupling<\/strong><\/h3>\n\n\n\n<p>This approach to coupling is not the only possible way; it\u2019s a design decision. You could:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Replace a supplier with supplied data<\/strong>. (See the article by Mike Hill in the <a href=\"#references\">References<\/a>.) If the collaborator gives you a stream of data, you might be able to pass in the data instead of the collaborator. The data could be in the form of an Array or Stream (etc.); this removes our dependency on the source itself.&nbsp;<\/li><li><strong>Pass in a closure<\/strong>. Instead of an object to talk to, you may be able to pass in a function reference (closure) and call through that. The closure may be easier to replace for testing, and you\u2019ve simplified the dependency.<\/li><li><strong>Apply other patterns<\/strong>: James Shore (see <a href=\"#references\">References<\/a>) has a whole pattern language on working without mocks.&nbsp;<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Objects with Global Values<\/strong><\/h2>\n\n\n\n<p>If a class depends on global variables (including static variables), it becomes trickier to understand and test. To test these, we set up the global object as well as the object to be tested:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Set up the global value\nCreate the object\nCall any methods needed to get it into the right state\n\nCall the method whose behavior you\u2019re testing\n\nCall \u201cobserver\u201d methods to verify the object\u2019s state is as expected\nIf needed, call observer methods on the global object you used<\/pre>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/global1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"500\" height=\"193\" src=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/global1.png\" alt=\"Global value: input to output, new global value state, new state of object\" class=\"wp-image-5307\" srcset=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/global1.png 500w, https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/global1-300x116.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>The problem with global state isn\u2019t so much \u201cDoes it act as we expect when everything is set up right?\u201d but rather \u201cIs the global state set up right when we want to use it?\u201d<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Reducing Complexity<\/strong><\/h3>\n\n\n\n<p>We can restructure to reduce the use of globals. One way is to make it a parameter, passing it in to anything that uses it. This turns an implicit dependency into an explicit one.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Objects with Global Collaborators<\/strong><\/h2>\n\n\n\n<p>Much like working with global or static values, the test will need to set up the global object that it collaborates with.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/global2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"500\" height=\"299\" src=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/global2.png\" alt=\"Global collaborators: input to new global state, new state of object, and new state of collaborators\" class=\"wp-image-5308\" srcset=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/global2.png 500w, https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/global2-300x179.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>As with the earlier global value type, the challenge is that a global could change \u201cbehind our back.\u201d<\/p>\n\n\n\n<p>[Added 2021-06-24] It&#8217;s not hard to reach this level of complexity. For example, you might have a purchasing application &#8211; the global is the system log used for audits (directly accessed by your class); the output is a receipt and tracking code; and the collaborators are a price sheet (to look up the cost of items), and a third-party service that requires the conversation to follow a certain protocol. <\/p>\n\n\n\n<p>To address the design issue, you can either pass in the global, or use one of the other mock-removal techniques.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>The connections we make between objects affect how they\u2019re tested and how complex they are. We looked at a few varieties of connection types, and some ways to simplify the more complex ones.&nbsp;<\/p>\n\n\n\n<p>Notice how many side effects we trigger if we use the more complex forms &#8211; and side effects are not our friend!<\/p>\n\n\n\n<p>We aren\u2019t necessarily trying to make every object of the simplest form, but rather to balance out our considerations, to lower our complexity and increase our ability to change code.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"references\"><strong>References<\/strong><\/h2>\n\n\n\n<p>Hill, Mike. \u201cUse Supplier or Supplied or Both?\u201d <a href=\"https:\/\/www.geepawhill.org\/2018\/03\/31\/use-supplier-or-supplied-or-both\/\">https:\/\/www.geepawhill.org\/2018\/03\/31\/use-supplier-or-supplied-or-both\/<\/a> &#8211; Retrieved 2021-06-21.<\/p>\n\n\n\n<p>Okasaki, Chris. <em><a href=\"http:\/\/www.amazon.com\/exec\/obidos\/ASIN\/0521663504\/xp123com\" target=\"_blank\" rel=\"noreferrer noopener sponsored nofollow\">Purely Functional Data Structures<\/a><\/em>. Cambridge University Press, 1999.&nbsp;<\/p>\n\n\n\n<p>Shore, James. \u201cTesting Without Mocks.\u201d <a href=\"https:\/\/www.jamesshore.com\/v2\/blog\/2018\/testing-without-mocks\">https:\/\/www.jamesshore.com\/v2\/blog\/2018\/testing-without-mocks<\/a> &#8211; Retrieved 2021-06-21.<\/p>\n\n\n\n<p>Wake, Bill. \u201cList-Like Objects &#8211; TDD Patterns.\u201d <a href=\"https:\/\/xp123.com\/articles\/list-like-objects-tdd-patterns\/\">https:\/\/xp123.com\/articles\/list-like-objects-tdd-patterns\/<\/a> &#8211; Retrieved 2021-06-21.<\/p>\n\n\n\n<p>Wake, Bill. \u201cSet-Like Objects &#8211; TDD Patterns.\u201d <a href=\"https:\/\/xp123.com\/articles\/set-like-objects-tdd-patterns\/\">https:\/\/xp123.com\/articles\/set-like-objects-tdd-patterns\/<\/a> &#8211; Retrieved 2021-06-21.<\/p>\n\n\n\n<p>Wake, Bill. \u201cTree-Like Objects &#8211; TDD Patterns.\u201d <a href=\"https:\/\/xp123.com\/articles\/tree-like-objects-tdd-patterns\/\">https:\/\/xp123.com\/articles\/tree-like-objects-tdd-patterns\/<\/a> &#8211; Retrieved 2021-06-21.<\/p>\n\n\n\n<div class=\"convertkit-form\">\n\n\n<div class=\"convertkit-form wp-block-convertkit-form\" style=\"\"><script async data-uid=\"44f57802e4\" src=\"https:\/\/xp123.kit.com\/44f57802e4\/index.js\" data-jetpack-boost=\"ignore\" data-no-defer=\"1\" data-no-optimize=\"1\" nowprocket><\/script><\/div>\n\n\n\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>When working with objects, there are different ways you can make them interact. We\u2019ll take a quick look at a variety of connections, what\u2019s needed to test them, and some alternatives you might consider.&nbsp; The connections below are in generally <a class=\"more-link\" href=\"https:\/\/xp123.com\/testing-objects-and-relationships\/\">Continue reading <span class=\"screen-reader-text\">  Testing Objects and Relationships<\/span><span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_wp_convertkit_post_meta":{"form":"-1","landing_page":"","tag":"0"},"footnotes":""},"categories":[1],"tags":[97,109],"class_list":["post-5301","post","type-post","status-publish","format-standard","hentry","category-xp123","tag-tdd","tag-xp"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Testing Objects and Relationships - XP123<\/title>\n<meta name=\"description\" content=\"Objects interact in different ways. We\u2019ll look at their connections, what\u2019s needed to test them, and some alternative design options.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/xp123.com\/testing-objects-and-relationships\/\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Bill Wake\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/xp123.com\\\/testing-objects-and-relationships\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/testing-objects-and-relationships\\\/\"},\"author\":{\"name\":\"Bill Wake\",\"@id\":\"https:\\\/\\\/xp123.com\\\/#\\\/schema\\\/person\\\/72474af0de7f699327fcff15bebf04c9\"},\"headline\":\"Testing Objects and Relationships\",\"datePublished\":\"2021-06-23T16:02:43+00:00\",\"dateModified\":\"2021-11-14T02:36:13+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/testing-objects-and-relationships\\\/\"},\"wordCount\":960,\"publisher\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/#\\\/schema\\\/person\\\/72474af0de7f699327fcff15bebf04c9\"},\"image\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/testing-objects-and-relationships\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2021\\\/06\\\/pure-fn.png\",\"keywords\":[\"tdd\",\"XPlorations\"],\"articleSection\":[\"xp123.com\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/xp123.com\\\/testing-objects-and-relationships\\\/\",\"url\":\"https:\\\/\\\/xp123.com\\\/testing-objects-and-relationships\\\/\",\"name\":\"Testing Objects and Relationships - XP123\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/testing-objects-and-relationships\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/testing-objects-and-relationships\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2021\\\/06\\\/pure-fn.png\",\"datePublished\":\"2021-06-23T16:02:43+00:00\",\"dateModified\":\"2021-11-14T02:36:13+00:00\",\"description\":\"Objects interact in different ways. We\u2019ll look at their connections, what\u2019s needed to test them, and some alternative design options.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/testing-objects-and-relationships\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/xp123.com\\\/testing-objects-and-relationships\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/xp123.com\\\/testing-objects-and-relationships\\\/#primaryimage\",\"url\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2021\\\/06\\\/pure-fn.png\",\"contentUrl\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2021\\\/06\\\/pure-fn.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/xp123.com\\\/testing-objects-and-relationships\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/xp123.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Testing Objects and Relationships\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/xp123.com\\\/#website\",\"url\":\"https:\\\/\\\/xp123.com\\\/\",\"name\":\"XP123\",\"description\":\"Exploring Extreme Programming\",\"publisher\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/#\\\/schema\\\/person\\\/72474af0de7f699327fcff15bebf04c9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/xp123.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/xp123.com\\\/#\\\/schema\\\/person\\\/72474af0de7f699327fcff15bebf04c9\",\"name\":\"Bill Wake\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2022\\\/09\\\/bill2012.jpeg\",\"url\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2022\\\/09\\\/bill2012.jpeg\",\"contentUrl\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2022\\\/09\\\/bill2012.jpeg\",\"width\":200,\"height\":200,\"caption\":\"Bill Wake\"},\"logo\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2022\\\/09\\\/bill2012.jpeg\"},\"sameAs\":[\"http:\\\/\\\/xp123.com\"],\"url\":\"https:\\\/\\\/xp123.com\\\/author\\\/bill\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Testing Objects and Relationships - XP123","description":"Objects interact in different ways. We\u2019ll look at their connections, what\u2019s needed to test them, and some alternative design options.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/xp123.com\/testing-objects-and-relationships\/","twitter_misc":{"Written by":"Bill Wake","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/xp123.com\/testing-objects-and-relationships\/#article","isPartOf":{"@id":"https:\/\/xp123.com\/testing-objects-and-relationships\/"},"author":{"name":"Bill Wake","@id":"https:\/\/xp123.com\/#\/schema\/person\/72474af0de7f699327fcff15bebf04c9"},"headline":"Testing Objects and Relationships","datePublished":"2021-06-23T16:02:43+00:00","dateModified":"2021-11-14T02:36:13+00:00","mainEntityOfPage":{"@id":"https:\/\/xp123.com\/testing-objects-and-relationships\/"},"wordCount":960,"publisher":{"@id":"https:\/\/xp123.com\/#\/schema\/person\/72474af0de7f699327fcff15bebf04c9"},"image":{"@id":"https:\/\/xp123.com\/testing-objects-and-relationships\/#primaryimage"},"thumbnailUrl":"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/pure-fn.png","keywords":["tdd","XPlorations"],"articleSection":["xp123.com"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/xp123.com\/testing-objects-and-relationships\/","url":"https:\/\/xp123.com\/testing-objects-and-relationships\/","name":"Testing Objects and Relationships - XP123","isPartOf":{"@id":"https:\/\/xp123.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/xp123.com\/testing-objects-and-relationships\/#primaryimage"},"image":{"@id":"https:\/\/xp123.com\/testing-objects-and-relationships\/#primaryimage"},"thumbnailUrl":"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/pure-fn.png","datePublished":"2021-06-23T16:02:43+00:00","dateModified":"2021-11-14T02:36:13+00:00","description":"Objects interact in different ways. We\u2019ll look at their connections, what\u2019s needed to test them, and some alternative design options.","breadcrumb":{"@id":"https:\/\/xp123.com\/testing-objects-and-relationships\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/xp123.com\/testing-objects-and-relationships\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/xp123.com\/testing-objects-and-relationships\/#primaryimage","url":"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/pure-fn.png","contentUrl":"https:\/\/xp123.com\/wp-content\/uploads\/2021\/06\/pure-fn.png"},{"@type":"BreadcrumbList","@id":"https:\/\/xp123.com\/testing-objects-and-relationships\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/xp123.com\/"},{"@type":"ListItem","position":2,"name":"Testing Objects and Relationships"}]},{"@type":"WebSite","@id":"https:\/\/xp123.com\/#website","url":"https:\/\/xp123.com\/","name":"XP123","description":"Exploring Extreme Programming","publisher":{"@id":"https:\/\/xp123.com\/#\/schema\/person\/72474af0de7f699327fcff15bebf04c9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/xp123.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/xp123.com\/#\/schema\/person\/72474af0de7f699327fcff15bebf04c9","name":"Bill Wake","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/xp123.com\/wp-content\/uploads\/2022\/09\/bill2012.jpeg","url":"https:\/\/xp123.com\/wp-content\/uploads\/2022\/09\/bill2012.jpeg","contentUrl":"https:\/\/xp123.com\/wp-content\/uploads\/2022\/09\/bill2012.jpeg","width":200,"height":200,"caption":"Bill Wake"},"logo":{"@id":"https:\/\/xp123.com\/wp-content\/uploads\/2022\/09\/bill2012.jpeg"},"sameAs":["http:\/\/xp123.com"],"url":"https:\/\/xp123.com\/author\/bill\/"}]}},"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/posts\/5301","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/comments?post=5301"}],"version-history":[{"count":1,"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/posts\/5301\/revisions"}],"predecessor-version":[{"id":5618,"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/posts\/5301\/revisions\/5618"}],"wp:attachment":[{"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/media?parent=5301"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/categories?post=5301"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/tags?post=5301"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}