{"id":1011,"date":"2017-07-06T13:07:37","date_gmt":"2017-07-06T17:07:37","guid":{"rendered":"https:\/\/blogs.mathworks.com\/developer\/?p=1011"},"modified":"2017-07-06T13:07:37","modified_gmt":"2017-07-06T17:07:37","slug":"dont-mock-me","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/developer\/2017\/07\/06\/dont-mock-me\/","title":{"rendered":"Don&#8217;t Mock Me!"},"content":{"rendered":"\r\n<div class=\"content\"><!--introduction--><!--\/introduction--><p><i>Hi folks, it's been a long time! Thanks for your patience as we have a lot of great incubating topics to discuss on the blog. Today I am excited to introduce David Hruska, who is the lead developer on an exciting new mocking framework that is part of MATLAB as of R2017b, and he is here to explore it a bit with you. Enjoy!<\/i><\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/DoMockMe.png\" alt=\"\"> <\/p><p>Do you mock when writing code? No, I'm not talking about <a href=\"http:\/\/dilbert.com\/strip\/2013-02-24\">this<\/a> kind of mocking. I'm talking about replacing the dependencies of your system-under-test with mock objects to drive the system's behavior a particular way, or verify how it interacts with its collaborators. MATLAB release 2017a includes a mocking framework for just this purpose. Let's look at an example in action to see what this means in practice. Here's the interface for an <tt>Iterator<\/tt> class that we'll be using.<\/p><pre class=\"language-matlab\"><span class=\"keyword\">classdef<\/span> Iterator &lt; handle\r\n   <span class=\"keyword\">properties<\/span> (Abstract, SetAccess=private)\r\n      Value;\r\n   <span class=\"keyword\">end<\/span>\r\n   <span class=\"keyword\">methods<\/span> (Abstract)\r\n      bool = hasNext(iter);\r\n      advance(iter);\r\n   <span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><p>And here's an algorithm we want to test. It determines if a value is present in the iterator.<\/p><pre class=\"language-matlab\"><span class=\"keyword\">function<\/span> bool = hasValue(iter, value)\r\nvalidateattributes(iter, {<span class=\"string\">'Iterator'<\/span>}, {<span class=\"string\">'scalar'<\/span>}, <span class=\"string\">'hasValue'<\/span>);\r\nvalidateattributes(value, {<span class=\"string\">'numeric'<\/span>}, {<span class=\"string\">'nonempty'<\/span>}, <span class=\"string\">'hasValue'<\/span>);\r\n\r\nbool = false;\r\n<span class=\"keyword\">while<\/span> iter.hasNext\r\n   iter.advance;\r\n   <span class=\"keyword\">if<\/span> iter.Value == value\r\n      bool = true;\r\n   <span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><p><b>Constructing a mock<\/b><\/p><p>To construct a mock, call the <tt>createMock<\/tt> method of the <tt>matlab.mock.TestCase<\/tt> class. Typically this would be used inside of a test method in a class which derives from <tt>matlab.mock.TestCase<\/tt>. However, for interactive experimentation at the command line, we'll first use the <tt>forInteractiveUse<\/tt> static method to obtain a <tt>TestCase<\/tt> instance. A call to the <tt>createMock<\/tt> method is all that's required to create a mock object. The framework creates a class that implements the necessary abstract properties and methods of the interface and constructs an instance. <tt>createMock<\/tt> also returns an associated <tt>behavior<\/tt> object for controlling the mock.<\/p><pre class=\"codeinput\">testCase = matlab.mock.TestCase.forInteractiveUse;\r\n[mockIterator, behavior] = testCase.createMock(?Iterator);\r\n<\/pre><p>To make the mock do something useful, we'll need to define its behavior. The behavior specification reads like a sentence:<\/p><pre class=\"codeinput\">import <span class=\"string\">matlab.mock.actions.AssignOutputs<\/span>;\r\nwhen(get(behavior.Value), then(AssignOutputs(1), then(AssignOutputs(2), then(AssignOutputs(3)))));\r\n<\/pre><p>Here's what this code does: when the <tt>Value<\/tt> property is accessed, first return a value of <tt>1<\/tt> . The next time the property is accessed, return a value of <tt>2<\/tt> . Finally, return <tt>3<\/tt> for any subsequent property accesses.<\/p><p>Let's also set up the <tt>hasNext<\/tt> method to return <tt>true<\/tt> the first three times it's invoked and <tt>false<\/tt> thereafter. Use <tt>withAnyInputs<\/tt> to specify that this behavior should be performed regardless of any additional inputs passed to the method.<\/p><pre class=\"codeinput\">when(withAnyInputs(behavior.hasNext), then(repeat(3, AssignOutputs(true)), then(AssignOutputs(false))));\r\n<\/pre><p>With some basic behavior defined, we can now use the mock to test our algorithm.<\/p><pre class=\"codeinput\">result = hasValue(mockIterator, 2);\r\ntestCase.verifyTrue(result, <span class=\"string\">\"Expected hasValue to find 2.\"<\/span>);\r\n<\/pre><pre class=\"codeoutput\">Interactive verification passed.\r\n<\/pre><p>The mock iterator was set up to return <tt>1<\/tt> , then <tt>2<\/tt> , then <tt>3<\/tt> ; the <tt>hasValue<\/tt> function found the <tt>2<\/tt> ; and the we've verified this outcome. Great!<\/p><p>The example above uses a technique sometimes referred to as <i>stubbing<\/i>: we have set up a mock to return pre-defined responses to drive the system in a particular way. We can also <i>spy<\/i> on how the system interacts with its dependencies. Let's set up a new mock with slightly different behavior and pass it to <tt>hasValue<\/tt>.<\/p><pre class=\"codeinput\">[mockIterator, behavior] = testCase.createMock(?Iterator);\r\nwhen(get(behavior.Value), then(AssignOutputs(1)));\r\nwhen(withAnyInputs(behavior.hasNext), then(repeat(10, AssignOutputs(true)), then(AssignOutputs(false))));\r\n\r\nresult = hasValue(mockIterator, 1);\r\ntestCase.assertTrue(result, <span class=\"string\">\"Expected hasValue to find 1.\"<\/span>);\r\n<\/pre><pre class=\"codeoutput\">Interactive assertion passed.\r\n<\/pre><p>Here we've defined the mock to always return value <tt>1<\/tt> when its <tt>Value<\/tt> property is accessed. The <tt>hasNext<\/tt> method returns <tt>true<\/tt> the first <tt>10<\/tt> times it is called, indicating that there are <tt>10<\/tt> values in the iterator. It would be reasonable to expect an efficient implementation of <tt>hasValue<\/tt> to \"short-circuit\" once it has found the first value and stop checking the remaining elements in the iterator. Let's see if this is what happened, though. When the mock is constructed, it automatically begins recording information about its interactions. In addition to defining how the mock should act, the <tt>behavior<\/tt> also provides access to this spy information. Let's use this information to verify that <tt>Value<\/tt> was accessed exactly once, as an efficient implementation would do.<\/p><pre class=\"codeinput\">import <span class=\"string\">matlab.mock.constraints.WasAccessed<\/span>;\r\ntestCase.verifyThat(behavior.Value, WasAccessed(<span class=\"string\">'WithCount'<\/span>,1), <span class=\"keyword\">...<\/span>\r\n    <span class=\"string\">\"Expected Value to be accessed only once.\"<\/span>);\r\n<\/pre><pre class=\"codeoutput\">Interactive verification failed.\r\n\r\n----------------\r\nTest Diagnostic:\r\n----------------\r\nExpected Value to be accessed only once.\r\n\r\n---------------------\r\nFramework Diagnostic:\r\n---------------------\r\nWasAccessed failed.\r\n--&gt; Property 'Value' was not accessed the expected number of times.\r\n    \r\n    Actual property access count:\r\n            10\r\n    Expected property access count:\r\n             1\r\n\r\nSpecified property access:\r\n    PropertyGetBehavior\r\n        &lt;IteratorMock_1&gt;.Value\r\n<\/pre><p>The qualification failed because the algorithm accessed the property <tt>10<\/tt> times. This could be addressed by returning immediately from the function after it finds the first instance of the desired value.<\/p><pre class=\"language-matlab\"><span class=\"keyword\">function<\/span> bool = efficientHasValue(iter, value)\r\nvalidateattributes(iter, {<span class=\"string\">'Iterator'<\/span>}, {<span class=\"string\">'scalar'<\/span>}, <span class=\"string\">'efficientHasValue'<\/span>);\r\nvalidateattributes(value, {<span class=\"string\">'numeric'<\/span>}, {<span class=\"string\">'nonempty'<\/span>}, <span class=\"string\">'efficientHasValue'<\/span>);\r\n\r\nbool = false;\r\n<span class=\"keyword\">while<\/span> iter.hasNext\r\n   iter.advance;\r\n   <span class=\"keyword\">if<\/span> iter.Value == value\r\n      bool = true;\r\n      <span class=\"comment\">% Done! We've found the value.<\/span>\r\n      <span class=\"keyword\">return<\/span>;\r\n   <span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><p>Returning to the original algorithm, let's write one more test. This time let's write a negative test to ensure the proper error checking is performed on the <tt>value<\/tt> input to <tt>hasValue<\/tt>, rejecting empty values. For this test, we don't plan to even use an Iterator, but we do need to provide a valid instance because the function also validates the iterator input. Therefore, we can simply construct a mock but define no behavior. The mock is then passed to the function being tested.<\/p><pre class=\"codeinput\">dummyIterator = testCase.createMock(?Iterator);\r\ntestCase.verifyError(@()hasValue(dummyIterator, []), <span class=\"string\">'MATLAB:hasValue:expectedNonempty'<\/span>);\r\n<\/pre><pre class=\"codeoutput\">Interactive verification passed.\r\n<\/pre><p><b>Comparison with Hand-Coded Mocks<\/b><\/p><p>The tests above could have been performed using hand-written mock subclasses of the <tt>Iterator<\/tt> interface. However, this can lead to one of two things: an inventory of many different mocks (stubs, spies, fakes, etc.) or one very complicated mock class that might even be more complicated that the code you're trying to test! For example, we might have been tempted to reuse the hand-written stub or spy for the negative test above which could result in undesirable coupling. By using the mocking framework, we achieve independence of each test.<\/p><p>Also, as your design evolves, your interfaces might change: new abstract properties or methods could be added. Or maybe the access permissions might change. This is particularly likely early in the development process. Hand-written mocks would need to be updated individually to relect the changes to the interface. The mocking framework, on the other hand, automatically implements all abstract members required by the interface with the correct access permissions each time <tt>createMock<\/tt> is called.<\/p><p>In summary, compared to hand-coded mocks, the mocking framework provides<\/p><div><ul><li>Isolation and independence of different tests<\/li><li>Clear visibility into tests with fewer additional files to look at<\/li><\/ul><\/div><p>What is the cost? The convenience does come at the cost of performance: if you're frequently reusing the exact same mock class, hand-coding will result in faster test execution time. However, the mocking framework overhead is likely small enough to be insignificant in most testing scenarios.<\/p><p>There's a lot more the framework can do, so check out the <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/mocking-framework.html\">documentation<\/a>. Have you used mocking in your testing workflows? Let us know in the comments below.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_d6a3407da43b4e67863882185d5c6a01() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='d6a3407da43b4e67863882185d5c6a01 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' d6a3407da43b4e67863882185d5c6a01';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2017 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_d6a3407da43b4e67863882185d5c6a01()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2017a<br><\/p><\/div><!--\r\nd6a3407da43b4e67863882185d5c6a01 ##### SOURCE BEGIN #####\r\n\r\n%%\r\n% _Hi folks, it's been a long time! Thanks for your patience as we have a\r\n% lot of great incubating topics to discuss on the blog. Today I am excited\r\n% to introduce David Hruska, who is the lead developer on an exciting new\r\n% mocking framework that is part of MATLAB as of R2017b, and he is here to\r\n% explore it a bit with you. Enjoy!_\r\n%\r\n% <<DoMockMe.png>>\r\n% \r\n% Do you mock when writing code? No, I'm not talking about\r\n% <http:\/\/dilbert.com\/strip\/2013-02-24 this> kind of mocking. I'm talking\r\n% about replacing the dependencies of your system-under-test with mock\r\n% objects to drive the system's behavior a particular way, or verify how it\r\n% interacts with its collaborators. MATLAB release 2017a includes a mocking\r\n% framework for just this purpose. Let's look at an example in action to\r\n% see what this means in practice. Here's the interface for an |Iterator|\r\n% class that we'll be using.\r\n%%\r\n% \r\n%   classdef Iterator < handle\r\n%      properties (Abstract, SetAccess=private)\r\n%         Value;\r\n%      end\r\n%      methods (Abstract)\r\n%         bool = hasNext(iter);\r\n%         advance(iter);\r\n%      end\r\n%   end\r\n% \r\n\r\n%%\r\n% And here's an algorithm we want to test. It determines if a value is\r\n% present in the iterator.\r\n%%\r\n%   function bool = hasValue(iter, value)\r\n%   validateattributes(iter, {'Iterator'}, {'scalar'}, 'hasValue');\r\n%   validateattributes(value, {'numeric'}, {'nonempty'}, 'hasValue');\r\n%   \r\n%   bool = false;\r\n%   while iter.hasNext\r\n%      iter.advance;\r\n%      if iter.Value == value\r\n%         bool = true;\r\n%      end\r\n%   end\r\n%   end\r\n% \r\n\r\n%%\r\n% *Constructing a mock*\r\n%\r\n% To construct a mock, call the |createMock| method of the\r\n% |matlab.mock.TestCase| class. Typically this would be used inside of a\r\n% test method in a class which derives from |matlab.mock.TestCase|.\r\n% However, for interactive experimentation at the command line, we'll first\r\n% use the |forInteractiveUse| static method to obtain a |TestCase|\r\n% instance. A call to the |createMock| method is all that's required to\r\n% create a mock object. The framework creates a class that implements the\r\n% necessary abstract properties and methods of the interface and constructs\r\n% an instance. |createMock| also returns an associated |behavior| object\r\n% for controlling the mock.\r\ntestCase = matlab.mock.TestCase.forInteractiveUse;\r\n[mockIterator, behavior] = testCase.createMock(?Iterator);\r\n\r\n%%\r\n% To make the mock do something useful, we'll need to define its behavior.\r\n% The behavior specification reads like a sentence:\r\nimport matlab.mock.actions.AssignOutputs;\r\nwhen(get(behavior.Value), then(AssignOutputs(1), then(AssignOutputs(2), then(AssignOutputs(3)))));\r\n\r\n%%\r\n% Here's what this code does: when the |Value| property is accessed, first\r\n% return a value of |1| . The next time the property is accessed, return a\r\n% value of |2| . Finally, return |3| for any subsequent property accesses.\r\n\r\n%%\r\n% Let's also set up the |hasNext| method to return |true| the first three\r\n% times it's invoked and |false| thereafter. Use |withAnyInputs| to specify\r\n% that this behavior should be performed regardless of any additional\r\n% inputs passed to the method.\r\nwhen(withAnyInputs(behavior.hasNext), then(repeat(3, AssignOutputs(true)), then(AssignOutputs(false))));\r\n\r\n%%\r\n% With some basic behavior defined, we can now use the mock to test our\r\n% algorithm.\r\nresult = hasValue(mockIterator, 2);\r\ntestCase.verifyTrue(result, \"Expected hasValue to find 2.\");\r\n\r\n%%\r\n% The mock iterator was set up to return |1| , then |2| , then |3| ; the\r\n% |hasValue| function found the |2| ; and the we've verified this outcome.\r\n% Great!\r\n\r\n%%\r\n% The example above uses a technique sometimes referred to as _stubbing_:\r\n% we have set up a mock to return pre-defined responses to drive the system\r\n% in a particular way. We can also _spy_ on how the system interacts with\r\n% its dependencies. Let's set up a new mock with slightly different\r\n% behavior and pass it to |hasValue|.\r\n[mockIterator, behavior] = testCase.createMock(?Iterator);\r\nwhen(get(behavior.Value), then(AssignOutputs(1)));\r\nwhen(withAnyInputs(behavior.hasNext), then(repeat(10, AssignOutputs(true)), then(AssignOutputs(false))));\r\n\r\nresult = hasValue(mockIterator, 1);\r\ntestCase.assertTrue(result, \"Expected hasValue to find 1.\");\r\n\r\n%%\r\n% Here we've defined the mock to always return value |1| when its |Value|\r\n% property is accessed. The |hasNext| method returns |true| the first |10|\r\n% times it is called, indicating that there are |10| values in the\r\n% iterator. It would be reasonable to expect an efficient implementation of\r\n% |hasValue| to \"short-circuit\" once it has found the first value and stop\r\n% checking the remaining elements in the iterator. Let's see if this is\r\n% what happened, though. When the mock is constructed, it automatically\r\n% begins recording information about its interactions. In addition to\r\n% defining how the mock should act, the |behavior| also provides access to\r\n% this spy information. Let's use this information to verify that |Value|\r\n% was accessed exactly once, as an efficient implementation would do.\r\nimport matlab.mock.constraints.WasAccessed;\r\ntestCase.verifyThat(behavior.Value, WasAccessed('WithCount',1), ...\r\n    \"Expected Value to be accessed only once.\");\r\n\r\n%%\r\n% The qualification failed because the algorithm accessed the property |10|\r\n% times. This could be addressed by returning immediately from the function\r\n% after it finds the first instance of the desired value.\r\n%%\r\n% \r\n%   function bool = efficientHasValue(iter, value)\r\n%   validateattributes(iter, {'Iterator'}, {'scalar'}, 'efficientHasValue');\r\n%   validateattributes(value, {'numeric'}, {'nonempty'}, 'efficientHasValue');\r\n%   \r\n%   bool = false;\r\n%   while iter.hasNext\r\n%      iter.advance;\r\n%      if iter.Value == value\r\n%         bool = true;\r\n%         % Done! We've found the value.\r\n%         return;\r\n%      end\r\n%   end\r\n%   end\r\n% \r\n\r\n\r\n%%\r\n% Returning to the original algorithm, let's write one more test. This time\r\n% let's write a negative test to ensure the proper error checking is\r\n% performed on the |value| input to |hasValue|, rejecting empty values. For\r\n% this test, we don't plan to even use an Iterator, but we do need to\r\n% provide a valid instance because the function also validates the iterator\r\n% input. Therefore, we can simply construct a mock but define no behavior.\r\n% The mock is then passed to the function being tested.\r\ndummyIterator = testCase.createMock(?Iterator);\r\ntestCase.verifyError(@()hasValue(dummyIterator, []), 'MATLAB:hasValue:expectedNonempty');\r\n\r\n%%\r\n% *Comparison with Hand-Coded Mocks*\r\n%\r\n% The tests above could have been performed using hand-written mock\r\n% subclasses of the |Iterator| interface. However, this can lead to one of\r\n% two things: an inventory of many different mocks (stubs, spies, fakes,\r\n% etc.) or one very complicated mock class that might even be more\r\n% complicated that the code you're trying to test! For example, we might\r\n% have been tempted to reuse the hand-written stub or spy for the negative\r\n% test above which could result in undesirable coupling. By using the\r\n% mocking framework, we achieve independence of each test.\r\n\r\n%%\r\n% Also, as your design evolves, your interfaces might change: new abstract\r\n% properties or methods could be added. Or maybe the access permissions\r\n% might change. This is particularly likely early in the development\r\n% process. Hand-written mocks would need to be updated individually to\r\n% relect the changes to the interface. The mocking framework, on the other\r\n% hand, automatically implements all abstract members required by the\r\n% interface with the correct access permissions each time |createMock| is\r\n% called.\r\n\r\n%%\r\n% In summary, compared to hand-coded mocks, the mocking framework provides\r\n%%\r\n% * Isolation and independence of different tests\r\n% * Clear visibility into tests with fewer additional files to look at\r\n%%\r\n% What is the cost? The convenience does come at the cost of performance:\r\n% if you're frequently reusing the exact same mock class, hand-coding will\r\n% result in faster test execution time. However, the mocking framework\r\n% overhead is likely small enough to be insignificant in most testing\r\n% scenarios.\r\n\r\n\r\n%%\r\n% There's a lot more the framework can do, so check out the\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/mocking-framework.html\r\n% documentation>. Have you used mocking in your testing workflows? Let us\r\n% know in the comments below.\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n##### SOURCE END ##### d6a3407da43b4e67863882185d5c6a01\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/DoMockMe.png\" onError=\"this.style.display ='none';\" \/><\/div><p>\r\nHi folks, it's been a long time! Thanks for your patience as we have a lot of great incubating topics to discuss on the blog. Today I am excited to introduce David Hruska, who is the lead developer... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/developer\/2017\/07\/06\/dont-mock-me\/\">read more >><\/a><\/p>","protected":false},"author":90,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[7],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/1011"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/users\/90"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/comments?post=1011"}],"version-history":[{"count":3,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/1011\/revisions"}],"predecessor-version":[{"id":1015,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/1011\/revisions\/1015"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/media?parent=1011"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/categories?post=1011"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/tags?post=1011"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}