1

The below code lives in an instance class with no constructor, I don't know from where to start writing unit tests for it.

E.g price is "2/9" so secondPart is 9 also the _random is an object of Random class

    public string RefreshPrice(string price, out bool isUpOrDown, out bool isChanged)
    {
        if (string.IsNullOrEmpty(price))
        {
            isUpOrDown = false;
            isChanged = false;
            return price;
        }

        int secondPart;
        string[] priceParts = price.Split('/');
        int newPrice = 0;
        if(int.TryParse(priceParts[1], out secondPart))
        {
            newPrice = secondPart >= 2 ? _random.Next(2, 20) : 2;
        }

        isUpOrDown = (newPrice > secondPart);
        isChanged = (newPrice != secondPart);

        secondPart = newPrice;
        return string.Format("{0}/{1}", priceParts[0], secondPart);
    }
George Stocker
  • 57,289
  • 29
  • 176
  • 237
HatSoft
  • 11,077
  • 3
  • 28
  • 43
  • I don't see any issue in this because your method does not depend on external resource, you don't need to mock, so what is your problem in here? – cuongle Oct 13 '12 at 17:54
  • @CuongLe I am not able to test it because of the dependency on Random.Next and the method takes out parameters – HatSoft Oct 13 '12 at 17:57
  • Random does not depend on external resource, let it be, why not so? – cuongle Oct 13 '12 at 17:58
  • But if you try to mock Random, only way is to use Reflection to fake value for private file _random. – cuongle Oct 13 '12 at 18:08
  • Added a link to a good answer about privates in unit testing: http://stackoverflow.com/questions/250692/how-do-you-unit-test-private-methods/4052474#4052474 – StuperUser Oct 13 '12 at 18:08
  • You don't have to use reflection, you can use: http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.privateobject(v=vs.80).aspx – StuperUser Oct 13 '12 at 18:09

1 Answers1

2

an instance class with no constructor

So this class will have a default ctor:

Legacy legacyUnderTest = new Legacy();

If _random is not set up in the default ctor, you should create a helper method getLegacyUnderTest to set _random, either how it is set in production or have a look at this stack overflow answer for accessing privates during tests using PrivateObject.

private Legacy getLegacyUnderTest()
{
    Legacy result = new Legacy();
    //set _random however it is set in production for the general need of your test
    return result;
}

Since they're out, you'll need to declare your bool flags as part of your arrange step for the test, then you're good to go:

[TestMethod]
public void RefreshPrice_EmptyPriceIsNotUpDownIsNotChange_ReturnsInitalPrice()
{
    //Arrange
    Legacy legacyUnderTest = new this.getLegacyUnderTest();
    bool isUpDown = false;
    bool isChange = false;
    string initialPrice = string.Empty;

    //Act
    string result = legacyUnderTest.RefreshPrice(initalPrice, isUpDown, isChange);

    //Assert
    Debug.IsEqual(initalPrice, result);
}

Now (after fixing the problems I've inevitably made by writing that snippet without VS in front of me) you'll just have to vary the values of isUpDown, isChange and initialPrice to cover all the possibilities you need to test and you should be good.

This should be the different formats of initial price (valid, null, empty and invalid formats) combined with the different true/false combinations of those flags.

Community
  • 1
  • 1
StuperUser
  • 10,555
  • 13
  • 78
  • 137