Repository files navigation

The World’s Most Awesome Parking Lot Manager Application

An exercise to introduce the concept of simulation in contrast to mocking.

Preliminaries

This exercise works best when you have access to an instance of Sql Server. You can use Sql Server Express if you don’t already have a Sql Server instance lying around. There is a script in the project called CreateValetDatabase.sql which will create the database and all the objects required by the initial project.

The initial implementation uses the packages xUnit.net, xUnit.net Extensions, and Fluent Assertions, which can all be installed using NuGet. If you’d like to run the tests in the Test Explorer (recommended) you should download and install “xUnt.net runner for Visual Studio 2012 and 2013” from the Visual Studio Gallery instead of using NuGet.

The code is not Clean. The original developer apparently decided that input validation was a passing fad. The unit tests are incomplete. The UI is tightly coupled to the object model. Consider these additional challenges to be surmounted, but don’t let them distract you from the primary goal of the exercise.

The Exercise

You'll find a simple Valet application. You'll note that the business logic layer has a set of unit tests. Run them and note that the server appears somewhat overtaxed.

Your primary task is to decouple the code from the database so that it won't be a chore to run the unit tests:

  1. Encapsulate the database access in an abstract class or interface.
  2. Change the unit tests so that you can easily run them against any implementation of the interface or abstract class.
  3. Use the unit tests to incrementally develop your alternative implementation.

Now, use your simulated storage system to add new functionality the application. Specifically, add the capability to look up the parking spots of all cars having a specific make, model, and color. Can you use the (awesome) UI with your implementation?

How can you make it easy to switch between implementations of the storage system in the application? Can you make it possible to switch in production without re-deploying?

After-action discussion

The pattern of replacing one implementation with another which is useful in a restricted context has been called “simulation”, with the implementation called a “simulator”*.

Your implementation probably doesn’t account for concurrent access to the storage system, and it probably doesn’t account for persistence across invocations of the application. These are the restrictions being placed on the context in which the simulator is valid, and those restrictions are perfectly reasonable for the purpose for which the simulator was created: To facilitate testing.

The fundamental advantage of using simulation instead of mocking is that drift between the implementations can be automatically detected. When using a mock object the test specifies the behavior or the object, with no connection to the real class. If the implementation of the real class changes the test can continue to pass even though the production code will fail. When using simulation the same tests can run against both implementations, providing you an automated way to detect these issues. These sorts of tests have been called "Contract tests".

This pattern is not always appropriate. For example, if there were a complicated stored procedure in the database that generated cryptographically strong ticket numbers using some bespoke algorithm then simulating that algorithm would probably require wholly re-implementing it. However, even in these cases some simulation may be feasible: Perhaps the majority of the tests, which presumably don’t care about the cryptographic strength of the ticket number, could run using the simulator, while the few that cover this facet could use the real implementation. Or perhaps the real implementation could be factored such that the simulator could make direct use of the cryptographic algorithm.

When using a tell-don't-ask-design you'll frequently end up with classes at the leaves of the model which have unobservable side effects. That is to say, the side effects will be unobservable through the interface. If the contract tests are to be run against multiple implementations then can they be used to verify that a particular implementation has performed one of these unobservable side effects, or do you need other tests? Do those tests belong in the same project as the contract tests? Does the component they test belong in the same project as the code that uses it?

Finally, an interesting point to consider is that the simulator is a legitimate implementation of an abstract concept. I.e. you expect the simulator to work with untested inputs. (Contrast with a mock.) This means that if you can find uses for your simulator in the production code there’s no reason not to use it. For example, could you implement a serializer for the simulator you developed, here? Or perhaps use a DataContractSerializer for it? Could you serialize the simulator to disk and load it from disk, so you didn’t need a database server, at all?


* This term was coined by Arlo Belshee

About

An exercise to introduce the concept of simulation in contrast to mocking.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

The World’s Most Awesome Parking Lot Manager Application

An exercise to introduce the concept of simulation in contrast to mocking.

Preliminaries

This exercise works best when you have access to an instance of Sql Server. You can use Sql Server Express if you don’t already have a Sql Server instance lying around. There is a script in the project called CreateValetDatabase.sql which will create the database and all the objects required by the initial project.

The initial implementation uses the packages xUnit.net, xUnit.net Extensions, and Fluent Assertions, which can all be installed using NuGet. If you’d like to run the tests in the Test Explorer (recommended) you should download and install “xUnt.net runner for Visual Studio 2012 and 2013” from the Visual Studio Gallery instead of using NuGet.

The code is not Clean. The original developer apparently decided that input validation was a passing fad. The unit tests are incomplete. The UI is tightly coupled to the object model. Consider these additional challenges to be surmounted, but don’t let them distract you from the primary goal of the exercise.

The Exercise

You'll find a simple Valet application. You'll note that the business logic layer has a set of unit tests. Run them and note that the server appears somewhat overtaxed.

Your primary task is to decouple the code from the database so that it won't be a chore to run the unit tests:

  1. Encapsulate the database access in an abstract class or interface.
  2. Change the unit tests so that you can easily run them against any implementation of the interface or abstract class.
  3. Use the unit tests to incrementally develop your alternative implementation.

Now, use your simulated storage system to add new functionality the application. Specifically, add the capability to look up the parking spots of all cars having a specific make, model, and color. Can you use the (awesome) UI with your implementation?

How can you make it easy to switch between implementations of the storage system in the application? Can you make it possible to switch in production without re-deploying?

After-action discussion

The pattern of replacing one implementation with another which is useful in a restricted context has been called “simulation”, with the implementation called a “simulator”*.

Your implementation probably doesn’t account for concurrent access to the storage system, and it probably doesn’t account for persistence across invocations of the application. These are the restrictions being placed on the context in which the simulator is valid, and those restrictions are perfectly reasonable for the purpose for which the simulator was created: To facilitate testing.

The fundamental advantage of using simulation instead of mocking is that drift between the implementations can be automatically detected. When using a mock object the test specifies the behavior or the object, with no connection to the real class. If the implementation of the real class changes the test can continue to pass even though the production code will fail. When using simulation the same tests can run against both implementations, providing you an automated way to detect these issues. These sorts of tests have been called "Contract tests".

This pattern is not always appropriate. For example, if there were a complicated stored procedure in the database that generated cryptographically strong ticket numbers using some bespoke algorithm then simulating that algorithm would probably require wholly re-implementing it. However, even in these cases some simulation may be feasible: Perhaps the majority of the tests, which presumably don’t care about the cryptographic strength of the ticket number, could run using the simulator, while the few that cover this facet could use the real implementation. Or perhaps the real implementation could be factored such that the simulator could make direct use of the cryptographic algorithm.

When using a tell-don't-ask-design you'll frequently end up with classes at the leaves of the model which have unobservable side effects. That is to say, the side effects will be unobservable through the interface. If the contract tests are to be run against multiple implementations then can they be used to verify that a particular implementation has performed one of these unobservable side effects, or do you need other tests? Do those tests belong in the same project as the contract tests? Does the component they test belong in the same project as the code that uses it?

Finally, an interesting point to consider is that the simulator is a legitimate implementation of an abstract concept. I.e. you expect the simulator to work with untested inputs. (Contrast with a mock.) This means that if you can find uses for your simulator in the production code there’s no reason not to use it. For example, could you implement a serializer for the simulator you developed, here? Or perhaps use a DataContractSerializer for it? Could you serialize the simulator to disk and load it from disk, so you didn’t need a database server, at all?


* This term was coined by Arlo Belshee

About

An exercise to introduce the concept of simulation in contrast to mocking.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

The World’s Most Awesome Parking Lot Manager Application

An exercise to introduce the concept of simulation in contrast to mocking.

Preliminaries

This exercise works best when you have access to an instance of Sql Server. You can use Sql Server Express if you don’t already have a Sql Server instance lying around. There is a script in the project called CreateValetDatabase.sql which will create the database and all the objects required by the initial project.

The initial implementation uses the packages xUnit.net, xUnit.net Extensions, and Fluent Assertions, which can all be installed using NuGet. If you’d like to run the tests in the Test Explorer (recommended) you should download and install “xUnt.net runner for Visual Studio 2012 and 2013” from the Visual Studio Gallery instead of using NuGet.

The code is not Clean. The original developer apparently decided that input validation was a passing fad. The unit tests are incomplete. The UI is tightly coupled to the object model. Consider these additional challenges to be surmounted, but don’t let them distract you from the primary goal of the exercise.

The Exercise

You'll find a simple Valet application. You'll note that the business logic layer has a set of unit tests. Run them and note that the server appears somewhat overtaxed.

Your primary task is to decouple the code from the database so that it won't be a chore to run the unit tests:

  1. Encapsulate the database access in an abstract class or interface.
  2. Change the unit tests so that you can easily run them against any implementation of the interface or abstract class.
  3. Use the unit tests to incrementally develop your alternative implementation.

Now, use your simulated storage system to add new functionality the application. Specifically, add the capability to look up the parking spots of all cars having a specific make, model, and color. Can you use the (awesome) UI with your implementation?

How can you make it easy to switch between implementations of the storage system in the application? Can you make it possible to switch in production without re-deploying?

After-action discussion

The pattern of replacing one implementation with another which is useful in a restricted context has been called “simulation”, with the implementation called a “simulator”*.

Your implementation probably doesn’t account for concurrent access to the storage system, and it probably doesn’t account for persistence across invocations of the application. These are the restrictions being placed on the context in which the simulator is valid, and those restrictions are perfectly reasonable for the purpose for which the simulator was created: To facilitate testing.

The fundamental advantage of using simulation instead of mocking is that drift between the implementations can be automatically detected. When using a mock object the test specifies the behavior or the object, with no connection to the real class. If the implementation of the real class changes the test can continue to pass even though the production code will fail. When using simulation the same tests can run against both implementations, providing you an automated way to detect these issues. These sorts of tests have been called "Contract tests".

This pattern is not always appropriate. For example, if there were a complicated stored procedure in the database that generated cryptographically strong ticket numbers using some bespoke algorithm then simulating that algorithm would probably require wholly re-implementing it. However, even in these cases some simulation may be feasible: Perhaps the majority of the tests, which presumably don’t care about the cryptographic strength of the ticket number, could run using the simulator, while the few that cover this facet could use the real implementation. Or perhaps the real implementation could be factored such that the simulator could make direct use of the cryptographic algorithm.

When using a tell-don't-ask-design you'll frequently end up with classes at the leaves of the model which have unobservable side effects. That is to say, the side effects will be unobservable through the interface. If the contract tests are to be run against multiple implementations then can they be used to verify that a particular implementation has performed one of these unobservable side effects, or do you need other tests? Do those tests belong in the same project as the contract tests? Does the component they test belong in the same project as the code that uses it?

Finally, an interesting point to consider is that the simulator is a legitimate implementation of an abstract concept. I.e. you expect the simulator to work with untested inputs. (Contrast with a mock.) This means that if you can find uses for your simulator in the production code there’s no reason not to use it. For example, could you implement a serializer for the simulator you developed, here? Or perhaps use a DataContractSerializer for it? Could you serialize the simulator to disk and load it from disk, so you didn’t need a database server, at all?


* This term was coined by Arlo Belshee

About

An exercise to introduce the concept of simulation in contrast to mocking.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

The World’s Most Awesome Parking Lot Manager Application

An exercise to introduce the concept of simulation in contrast to mocking.

Preliminaries

This exercise works best when you have access to an instance of Sql Server. You can use Sql Server Express if you don’t already have a Sql Server instance lying around. There is a script in the project called CreateValetDatabase.sql which will create the database and all the objects required by the initial project.

The initial implementation uses the packages xUnit.net, xUnit.net Extensions, and Fluent Assertions, which can all be installed using NuGet. If you’d like to run the tests in the Test Explorer (recommended) you should download and install “xUnt.net runner for Visual Studio 2012 and 2013” from the Visual Studio Gallery instead of using NuGet.

The code is not Clean. The original developer apparently decided that input validation was a passing fad. The unit tests are incomplete. The UI is tightly coupled to the object model. Consider these additional challenges to be surmounted, but don’t let them distract you from the primary goal of the exercise.

The Exercise

You'll find a simple Valet application. You'll note that the business logic layer has a set of unit tests. Run them and note that the server appears somewhat overtaxed.

Your primary task is to decouple the code from the database so that it won't be a chore to run the unit tests:

  1. Encapsulate the database access in an abstract class or interface.
  2. Change the unit tests so that you can easily run them against any implementation of the interface or abstract class.
  3. Use the unit tests to incrementally develop your alternative implementation.

Now, use your simulated storage system to add new functionality the application. Specifically, add the capability to look up the parking spots of all cars having a specific make, model, and color. Can you use the (awesome) UI with your implementation?

How can you make it easy to switch between implementations of the storage system in the application? Can you make it possible to switch in production without re-deploying?

After-action discussion

The pattern of replacing one implementation with another which is useful in a restricted context has been called “simulation”, with the implementation called a “simulator”*.

Your implementation probably doesn’t account for concurrent access to the storage system, and it probably doesn’t account for persistence across invocations of the application. These are the restrictions being placed on the context in which the simulator is valid, and those restrictions are perfectly reasonable for the purpose for which the simulator was created: To facilitate testing.

The fundamental advantage of using simulation instead of mocking is that drift between the implementations can be automatically detected. When using a mock object the test specifies the behavior or the object, with no connection to the real class. If the implementation of the real class changes the test can continue to pass even though the production code will fail. When using simulation the same tests can run against both implementations, providing you an automated way to detect these issues. These sorts of tests have been called "Contract tests".

This pattern is not always appropriate. For example, if there were a complicated stored procedure in the database that generated cryptographically strong ticket numbers using some bespoke algorithm then simulating that algorithm would probably require wholly re-implementing it. However, even in these cases some simulation may be feasible: Perhaps the majority of the tests, which presumably don’t care about the cryptographic strength of the ticket number, could run using the simulator, while the few that cover this facet could use the real implementation. Or perhaps the real implementation could be factored such that the simulator could make direct use of the cryptographic algorithm.

When using a tell-don't-ask-design you'll frequently end up with classes at the leaves of the model which have unobservable side effects. That is to say, the side effects will be unobservable through the interface. If the contract tests are to be run against multiple implementations then can they be used to verify that a particular implementation has performed one of these unobservable side effects, or do you need other tests? Do those tests belong in the same project as the contract tests? Does the component they test belong in the same project as the code that uses it?

Finally, an interesting point to consider is that the simulator is a legitimate implementation of an abstract concept. I.e. you expect the simulator to work with untested inputs. (Contrast with a mock.) This means that if you can find uses for your simulator in the production code there’s no reason not to use it. For example, could you implement a serializer for the simulator you developed, here? Or perhaps use a DataContractSerializer for it? Could you serialize the simulator to disk and load it from disk, so you didn’t need a database server, at all?


* This term was coined by Arlo Belshee

About

An exercise to introduce the concept of simulation in contrast to mocking.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

The World’s Most Awesome Parking Lot Manager Application

An exercise to introduce the concept of simulation in contrast to mocking.

Preliminaries

This exercise works best when you have access to an instance of Sql Server. You can use Sql Server Express if you don’t already have a Sql Server instance lying around. There is a script in the project called CreateValetDatabase.sql which will create the database and all the objects required by the initial project.

The initial implementation uses the packages xUnit.net, xUnit.net Extensions, and Fluent Assertions, which can all be installed using NuGet. If you’d like to run the tests in the Test Explorer (recommended) you should download and install “xUnt.net runner for Visual Studio 2012 and 2013” from the Visual Studio Gallery instead of using NuGet.

The code is not Clean. The original developer apparently decided that input validation was a passing fad. The unit tests are incomplete. The UI is tightly coupled to the object model. Consider these additional challenges to be surmounted, but don’t let them distract you from the primary goal of the exercise.

The Exercise

You'll find a simple Valet application. You'll note that the business logic layer has a set of unit tests. Run them and note that the server appears somewhat overtaxed.

Your primary task is to decouple the code from the database so that it won't be a chore to run the unit tests:

  1. Encapsulate the database access in an abstract class or interface.
  2. Change the unit tests so that you can easily run them against any implementation of the interface or abstract class.
  3. Use the unit tests to incrementally develop your alternative implementation.

Now, use your simulated storage system to add new functionality the application. Specifically, add the capability to look up the parking spots of all cars having a specific make, model, and color. Can you use the (awesome) UI with your implementation?

How can you make it easy to switch between implementations of the storage system in the application? Can you make it possible to switch in production without re-deploying?

After-action discussion

The pattern of replacing one implementation with another which is useful in a restricted context has been called “simulation”, with the implementation called a “simulator”*.

Your implementation probably doesn’t account for concurrent access to the storage system, and it probably doesn’t account for persistence across invocations of the application. These are the restrictions being placed on the context in which the simulator is valid, and those restrictions are perfectly reasonable for the purpose for which the simulator was created: To facilitate testing.

The fundamental advantage of using simulation instead of mocking is that drift between the implementations can be automatically detected. When using a mock object the test specifies the behavior or the object, with no connection to the real class. If the implementation of the real class changes the test can continue to pass even though the production code will fail. When using simulation the same tests can run against both implementations, providing you an automated way to detect these issues. These sorts of tests have been called "Contract tests".

This pattern is not always appropriate. For example, if there were a complicated stored procedure in the database that generated cryptographically strong ticket numbers using some bespoke algorithm then simulating that algorithm would probably require wholly re-implementing it. However, even in these cases some simulation may be feasible: Perhaps the majority of the tests, which presumably don’t care about the cryptographic strength of the ticket number, could run using the simulator, while the few that cover this facet could use the real implementation. Or perhaps the real implementation could be factored such that the simulator could make direct use of the cryptographic algorithm.

When using a tell-don't-ask-design you'll frequently end up with classes at the leaves of the model which have unobservable side effects. That is to say, the side effects will be unobservable through the interface. If the contract tests are to be run against multiple implementations then can they be used to verify that a particular implementation has performed one of these unobservable side effects, or do you need other tests? Do those tests belong in the same project as the contract tests? Does the component they test belong in the same project as the code that uses it?

Finally, an interesting point to consider is that the simulator is a legitimate implementation of an abstract concept. I.e. you expect the simulator to work with untested inputs. (Contrast with a mock.) This means that if you can find uses for your simulator in the production code there’s no reason not to use it. For example, could you implement a serializer for the simulator you developed, here? Or perhaps use a DataContractSerializer for it? Could you serialize the simulator to disk and load it from disk, so you didn’t need a database server, at all?


* This term was coined by Arlo Belshee

About

An exercise to introduce the concept of simulation in contrast to mocking.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

The World’s Most Awesome Parking Lot Manager Application

An exercise to introduce the concept of simulation in contrast to mocking.

Preliminaries

This exercise works best when you have access to an instance of Sql Server. You can use Sql Server Express if you don’t already have a Sql Server instance lying around. There is a script in the project called CreateValetDatabase.sql which will create the database and all the objects required by the initial project.

The initial implementation uses the packages xUnit.net, xUnit.net Extensions, and Fluent Assertions, which can all be installed using NuGet. If you’d like to run the tests in the Test Explorer (recommended) you should download and install “xUnt.net runner for Visual Studio 2012 and 2013” from the Visual Studio Gallery instead of using NuGet.

The code is not Clean. The original developer apparently decided that input validation was a passing fad. The unit tests are incomplete. The UI is tightly coupled to the object model. Consider these additional challenges to be surmounted, but don’t let them distract you from the primary goal of the exercise.

The Exercise

You'll find a simple Valet application. You'll note that the business logic layer has a set of unit tests. Run them and note that the server appears somewhat overtaxed.

Your primary task is to decouple the code from the database so that it won't be a chore to run the unit tests:

  1. Encapsulate the database access in an abstract class or interface.
  2. Change the unit tests so that you can easily run them against any implementation of the interface or abstract class.
  3. Use the unit tests to incrementally develop your alternative implementation.

Now, use your simulated storage system to add new functionality the application. Specifically, add the capability to look up the parking spots of all cars having a specific make, model, and color. Can you use the (awesome) UI with your implementation?

How can you make it easy to switch between implementations of the storage system in the application? Can you make it possible to switch in production without re-deploying?

After-action discussion

The pattern of replacing one implementation with another which is useful in a restricted context has been called “simulation”, with the implementation called a “simulator”*.

Your implementation probably doesn’t account for concurrent access to the storage system, and it probably doesn’t account for persistence across invocations of the application. These are the restrictions being placed on the context in which the simulator is valid, and those restrictions are perfectly reasonable for the purpose for which the simulator was created: To facilitate testing.

The fundamental advantage of using simulation instead of mocking is that drift between the implementations can be automatically detected. When using a mock object the test specifies the behavior or the object, with no connection to the real class. If the implementation of the real class changes the test can continue to pass even though the production code will fail. When using simulation the same tests can run against both implementations, providing you an automated way to detect these issues. These sorts of tests have been called "Contract tests".

This pattern is not always appropriate. For example, if there were a complicated stored procedure in the database that generated cryptographically strong ticket numbers using some bespoke algorithm then simulating that algorithm would probably require wholly re-implementing it. However, even in these cases some simulation may be feasible: Perhaps the majority of the tests, which presumably don’t care about the cryptographic strength of the ticket number, could run using the simulator, while the few that cover this facet could use the real implementation. Or perhaps the real implementation could be factored such that the simulator could make direct use of the cryptographic algorithm.

When using a tell-don't-ask-design you'll frequently end up with classes at the leaves of the model which have unobservable side effects. That is to say, the side effects will be unobservable through the interface. If the contract tests are to be run against multiple implementations then can they be used to verify that a particular implementation has performed one of these unobservable side effects, or do you need other tests? Do those tests belong in the same project as the contract tests? Does the component they test belong in the same project as the code that uses it?

Finally, an interesting point to consider is that the simulator is a legitimate implementation of an abstract concept. I.e. you expect the simulator to work with untested inputs. (Contrast with a mock.) This means that if you can find uses for your simulator in the production code there’s no reason not to use it. For example, could you implement a serializer for the simulator you developed, here? Or perhaps use a DataContractSerializer for it? Could you serialize the simulator to disk and load it from disk, so you didn’t need a database server, at all?


* This term was coined by Arlo Belshee

About

An exercise to introduce the concept of simulation in contrast to mocking.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

The World’s Most Awesome Parking Lot Manager Application

An exercise to introduce the concept of simulation in contrast to mocking.

Preliminaries

This exercise works best when you have access to an instance of Sql Server. You can use Sql Server Express if you don’t already have a Sql Server instance lying around. There is a script in the project called CreateValetDatabase.sql which will create the database and all the objects required by the initial project.

The initial implementation uses the packages xUnit.net, xUnit.net Extensions, and Fluent Assertions, which can all be installed using NuGet. If you’d like to run the tests in the Test Explorer (recommended) you should download and install “xUnt.net runner for Visual Studio 2012 and 2013” from the Visual Studio Gallery instead of using NuGet.

The code is not Clean. The original developer apparently decided that input validation was a passing fad. The unit tests are incomplete. The UI is tightly coupled to the object model. Consider these additional challenges to be surmounted, but don’t let them distract you from the primary goal of the exercise.

The Exercise

You'll find a simple Valet application. You'll note that the business logic layer has a set of unit tests. Run them and note that the server appears somewhat overtaxed.

Your primary task is to decouple the code from the database so that it won't be a chore to run the unit tests:

  1. Encapsulate the database access in an abstract class or interface.
  2. Change the unit tests so that you can easily run them against any implementation of the interface or abstract class.
  3. Use the unit tests to incrementally develop your alternative implementation.

Now, use your simulated storage system to add new functionality the application. Specifically, add the capability to look up the parking spots of all cars having a specific make, model, and color. Can you use the (awesome) UI with your implementation?

How can you make it easy to switch between implementations of the storage system in the application? Can you make it possible to switch in production without re-deploying?

After-action discussion

The pattern of replacing one implementation with another which is useful in a restricted context has been called “simulation”, with the implementation called a “simulator”*.

Your implementation probably doesn’t account for concurrent access to the storage system, and it probably doesn’t account for persistence across invocations of the application. These are the restrictions being placed on the context in which the simulator is valid, and those restrictions are perfectly reasonable for the purpose for which the simulator was created: To facilitate testing.

The fundamental advantage of using simulation instead of mocking is that drift between the implementations can be automatically detected. When using a mock object the test specifies the behavior or the object, with no connection to the real class. If the implementation of the real class changes the test can continue to pass even though the production code will fail. When using simulation the same tests can run against both implementations, providing you an automated way to detect these issues. These sorts of tests have been called "Contract tests".

This pattern is not always appropriate. For example, if there were a complicated stored procedure in the database that generated cryptographically strong ticket numbers using some bespoke algorithm then simulating that algorithm would probably require wholly re-implementing it. However, even in these cases some simulation may be feasible: Perhaps the majority of the tests, which presumably don’t care about the cryptographic strength of the ticket number, could run using the simulator, while the few that cover this facet could use the real implementation. Or perhaps the real implementation could be factored such that the simulator could make direct use of the cryptographic algorithm.

When using a tell-don't-ask-design you'll frequently end up with classes at the leaves of the model which have unobservable side effects. That is to say, the side effects will be unobservable through the interface. If the contract tests are to be run against multiple implementations then can they be used to verify that a particular implementation has performed one of these unobservable side effects, or do you need other tests? Do those tests belong in the same project as the contract tests? Does the component they test belong in the same project as the code that uses it?

Finally, an interesting point to consider is that the simulator is a legitimate implementation of an abstract concept. I.e. you expect the simulator to work with untested inputs. (Contrast with a mock.) This means that if you can find uses for your simulator in the production code there’s no reason not to use it. For example, could you implement a serializer for the simulator you developed, here? Or perhaps use a DataContractSerializer for it? Could you serialize the simulator to disk and load it from disk, so you didn’t need a database server, at all?


* This term was coined by Arlo Belshee

About

An exercise to introduce the concept of simulation in contrast to mocking.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

The World’s Most Awesome Parking Lot Manager Application

An exercise to introduce the concept of simulation in contrast to mocking.

Preliminaries

This exercise works best when you have access to an instance of Sql Server. You can use Sql Server Express if you don’t already have a Sql Server instance lying around. There is a script in the project called CreateValetDatabase.sql which will create the database and all the objects required by the initial project.

The initial implementation uses the packages xUnit.net, xUnit.net Extensions, and Fluent Assertions, which can all be installed using NuGet. If you’d like to run the tests in the Test Explorer (recommended) you should download and install “xUnt.net runner for Visual Studio 2012 and 2013” from the Visual Studio Gallery instead of using NuGet.

The code is not Clean. The original developer apparently decided that input validation was a passing fad. The unit tests are incomplete. The UI is tightly coupled to the object model. Consider these additional challenges to be surmounted, but don’t let them distract you from the primary goal of the exercise.

The Exercise

You'll find a simple Valet application. You'll note that the business logic layer has a set of unit tests. Run them and note that the server appears somewhat overtaxed.

Your primary task is to decouple the code from the database so that it won't be a chore to run the unit tests:

  1. Encapsulate the database access in an abstract class or interface.
  2. Change the unit tests so that you can easily run them against any implementation of the interface or abstract class.
  3. Use the unit tests to incrementally develop your alternative implementation.

Now, use your simulated storage system to add new functionality the application. Specifically, add the capability to look up the parking spots of all cars having a specific make, model, and color. Can you use the (awesome) UI with your implementation?

How can you make it easy to switch between implementations of the storage system in the application? Can you make it possible to switch in production without re-deploying?

After-action discussion

The pattern of replacing one implementation with another which is useful in a restricted context has been called “simulation”, with the implementation called a “simulator”*.

Your implementation probably doesn’t account for concurrent access to the storage system, and it probably doesn’t account for persistence across invocations of the application. These are the restrictions being placed on the context in which the simulator is valid, and those restrictions are perfectly reasonable for the purpose for which the simulator was created: To facilitate testing.

The fundamental advantage of using simulation instead of mocking is that drift between the implementations can be automatically detected. When using a mock object the test specifies the behavior or the object, with no connection to the real class. If the implementation of the real class changes the test can continue to pass even though the production code will fail. When using simulation the same tests can run against both implementations, providing you an automated way to detect these issues. These sorts of tests have been called "Contract tests".

This pattern is not always appropriate. For example, if there were a complicated stored procedure in the database that generated cryptographically strong ticket numbers using some bespoke algorithm then simulating that algorithm would probably require wholly re-implementing it. However, even in these cases some simulation may be feasible: Perhaps the majority of the tests, which presumably don’t care about the cryptographic strength of the ticket number, could run using the simulator, while the few that cover this facet could use the real implementation. Or perhaps the real implementation could be factored such that the simulator could make direct use of the cryptographic algorithm.

When using a tell-don't-ask-design you'll frequently end up with classes at the leaves of the model which have unobservable side effects. That is to say, the side effects will be unobservable through the interface. If the contract tests are to be run against multiple implementations then can they be used to verify that a particular implementation has performed one of these unobservable side effects, or do you need other tests? Do those tests belong in the same project as the contract tests? Does the component they test belong in the same project as the code that uses it?

Finally, an interesting point to consider is that the simulator is a legitimate implementation of an abstract concept. I.e. you expect the simulator to work with untested inputs. (Contrast with a mock.) This means that if you can find uses for your simulator in the production code there’s no reason not to use it. For example, could you implement a serializer for the simulator you developed, here? Or perhaps use a DataContractSerializer for it? Could you serialize the simulator to disk and load it from disk, so you didn’t need a database server, at all?


* This term was coined by Arlo Belshee

About

An exercise to introduce the concept of simulation in contrast to mocking.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages