I'm reading Clean Code: A Handbook of Agile Software Craftsmanship
and one of the examples involves a Portfolio
class and a TokyoStockExchange
class. However, Portfolio
is not very testable because it depends on TokyoStockExchange
as an external API to determine the value of the portfolio and such is quite a volatile lookup and not conducive to testing.
So, they solve this by creating a common StockExchange
interface and have TokyoStockExchange
and DummyStockExchange
both implement the base class. Thus, dependency inversion principle is attained and in the PortfolioTest
class one can instantiate a DummyStockExchange
, fix a stock price to a corporation, assign the DummyStockExchange
instance to the portfolio, and add some stocks from that company to the portfolio, and then assert if the expected value is indeed the proper value. Here's the code:
public class PortfolioTest
{
private DummyStockExchange exchange;
private Portfolio portfolio;
protected void setUp()
{
exchange = new DummyStockExchange();
exchange.fix("MSFT", 100);
portfolio = new Portfolio(exchange);
}
public void GivenFiveMSFTTotalShouldBe500()
{
portfolio.add(5, "MSFT");
Assert.assertEquals(500, portfolio.value());
}
}
My question, simply, is why?
We were trying test if the TokyoStockExchange
class worked in tandem with the Portfolio
class. Obviously if we create another class with a new method that sets a stock price and then give the portfolio five of those stocks then everything will work. It just seems.. useless to test. I understand that TokyoStockExchange
is basically impossible to test with Portfolio
because of the changing stock prices but I don't understand how subbing in a rather useless test helps the situation.
It all just seems akin to not knowing if our adder programs works but the only numbers available are randomly generated so we create a dummy class that gives us a 2 and test if 2 + 2 = 4
. Well yeah, obviously that is true. We can still break TokyoStockExchange
and the test will still succeed because it's testing another class. If anything this all seems deceptive and it also results in having to write additional code just to test something we know is going to work.
I think this is the biggest problem I have with understanding Unit Testing at this point. I know that I'm wrong I just have failed to see the light I guess. Hopefully someone can help me out.
Unit testing ensures that all code meets quality standards before it's deployed. This ensures a reliable engineering environment where quality is paramount. Over the course of the product development life cycle, unit testing saves time and money, and helps developers write better code, more efficiently.
You use mocks when you don't want to invoke production code or when there is no easy way to verify, that intended code was executed. There is no return value and no easy way to check system state change. An example can be a functionality that calls e-mail sending service.
Dummies, as the name implies, are simple objects that serve no real purpose other than being there when they're required. Their purpose is to be there when the syntax requires it. For example, imagine having to call a function that takes 3 arguments, with the first one being another function (an external dependency).
It is unlikely for mocking to be applicable in unit tests, as that means there is a part of the system the unit depends on, making that unit less isolated and less subjected to unit testing. Whenever you reach out to mock things in a unit test that is a good sign you are in fact writing an integration test.
The idea is that you would want to test the logic in the Portfolio
class in isolation from TokyoStockExchange
. If you use a mock framework like Moq or Rhino Mocks, then you can easily simulate different outputs and behaviors from TokyoStockExchange
and write unit tests to make sure that Portfolio
responds correctly. You would write separate unit tests for the TokyoStockExchange
class.
This is not to say that you don't need integration testing between the two classes. It's just hard to properly verify all scenarios without the use of mock objects.
It's hard to understand the value with such a simple class as an example, but given a more complex class where you need to verify test cases for situations which are hard to or impossible to arrange on a "live" class, unit testing becomes much more important.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With