1

I am using RhinoMocks for mocking/stubbing, and Nunit framework for unit testing.

I have following class

    class A
    {
        private int data = -1;

        public void Initialize (int data)
        {
            this.data = data;
        }

        public void CallA()
        {
            if (data == -1) throw new InvalidArgumentException("data has invalid value -1");
            try
            {

                A1("a1");
                A2("a2");
            }
            catch (AException e)
            {
                throw;
            }  

            catch (Exception e)
            {
                throw new AException(ErrorCode.UnknownException, e);
            }  
        }
        private void A1(string item)
        {
        }

        private void A2(string item)
        {
        }

    }

I am struggling to following test cases:

  1. InvalidAgrumentException : It will raised if either Initialized method is not called or -1 is passed as argument to Initialized. data is private So cannot be mocked (until libraries such as TypeMock isolater are used that do IL Weaving). To raise this exception, One option is to call Initialized Method which I am not sure is the correct approach? (because data can be set as -1 from other places also. Though that is not an issue it requires extra function call.)

  2. To verify that A1 is called with "a1" parameter, and A2 is called with "a2" parameter.

Community
  • 1
  • 1
Tilak
  • 30,108
  • 19
  • 83
  • 131

2 Answers2

4

Daniel makes a good point and I just want to expand his answer a little bit. Making you test depend on private method calls creates a very fragile test suite. Private method are implementation details and you should always be safe changing them with respect to changes in inner implementation and not to observe fail of 10-20 tests.

Another point of Initilize method - if it is hard to test imagine how hard to use your class. Robert Martin makes a good point in one of his books, that method doesn't say what other methods and in which order should be called before.

In your case, for example, public void CallA() says nothing on why when and with what args should Initialize be called. Why don't you create a constructor from Initialize with input arguments or call Initialize from constructor. Now you are sure it has been called. Another point is about magic number -1.

Sorry for criticizing, but I have worked with such designs and it's really hard to test them, regardless of what testing\mocking frameworks do you use. You can mock private method, you can stub static method calls, but it all ends up in good design, not the power of mocking framework.

Ilya Ivanov
  • 23,148
  • 4
  • 64
  • 90
  • +1: Initialize-family methods are always a great find after two hours debugging. – k.m Jan 16 '13 at 16:39
  • +1, NO issues with the criticism. Your post led me to [this](http://blog.ploeh.dk/2011/05/24/DesignSmellTemporalCoupling.aspx) and it will certainly help me avoiding such code smells (to the extent possible) in future – Tilak Jan 17 '13 at 03:47
2

You can't do that.

Mocking frameworks are used to mock dependencies of the class you want to test. Mocking the class itself makes no sense, because it would mean that you test a mock instead of your class.

Furthermore, verifying that a private method in your class has been called also isn't correct. You need to verify that some other way, two common approaches are:

  1. Verify that the class is in the correct state
  2. Verify that a certain method on a mocked dependency has been called

Which one you can and should use depends mainly on the class you want to test.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443