开发者

Is it a good idea to inject a TestSettings parameter to a method to make it (Unit or integration) Testable?

Is it a good practice to introduce a TestSettings class in order to provide flexible testing possibilities of a method that has many processes inside?

Maybe not a good example but can be simple: Suppose that I have this method and I want to test its sub-processes:

public void TheBigMethod(myMethodParameters parameter)
{

  if(parameter.Condition1)
   {
     MethodForCondition1("BigMac"); 
   }

  if(parameter.Condition2)
   {
     MethodForCondition2("MilkShake"); 
   }

  if(parameter.Condition3)
   {
     MethodForCondition3("Coke"); 
   }

  SomeCommonMethod1('A');
  SomeCommonMethod2('B');
  SomeCommonMethod3('C');
}

And imagine that I have unit tests for all

  • void MethodForCondition1 (string s)
  • void MethodForCondition2 (string s)
  • void MethodForCondition3 (string s)
  • void SomeCommonMethod1 (char c)
  • void SomeCommonMethod2 (char c)
  • void SomeCommonMethod3 (char c)

And now i want to test the TheBigMethod itself by introducing such test methods with required Asserts in them:

  • TheBigMetho开发者_JAVA百科d_MethodForCondition1_TestCaseX_DoesGood
  • TheBigMethod_MethodForCondition2_TestCaseY_DoesGood
  • TheBigMethod_MethodForCondition3_TestCaseZ_DoesGood
  • TheBigMethod_SomeCommonMethod1_TestCaseU_DoesGood
  • TheBigMethod_SomeCommonMethod2_TestCaseP_DoesGood
  • TheBigMethod_SomeCommonMethod3_TestCaseQ_DoesGood

So, I want TheBigMethod to be exit-able at some points if it is called by one of my integration tests above.

public void TheBigMethod(myMethodParameters parameter, TestSettings setting)
{

  if(parameter.Condition1)
   {
     MethodForCondition1("BigMac"); 

     if(setting.ExitAfter_MethodForCondition1)
        return;

   }

  if(parameter.Condition2)
   {
     MethodForCondition2("MilkShake"); 

     if(setting.ExitAfter_MethodForCondition2)
        return;

   }

  if(parameter.Condition3)
   {
     MethodForCondition3("Coke"); 

     if(setting.ExitAfter_MethodForCondition3)
        return;

   }

  SomeCommonMethod1('A');
  if(setting.ExitAfter_SomeCommonMethod1)
       return;

  SomeCommonMethod2('B');
  if(setting.ExitAfter_SomeCommonMethod2)
       return;

  SomeCommonMethod3('C');
  if(setting.ExitAfter_SomeCommonMethod3)
       return;
}

Even though it looks it does what I need to introduce a TestSetting parameter can makee the code less readable and does not look nice to have testing logic and the main functionality combined to me.

Can you advise a better design for such cases so that it can replace a TestSetting parameter idea?

thanks


It would (IMO) be a very bad thing to add this TestSetting. An alternative would be to add an interface (or set of interfaces) for MethodForConditionX and SomeCommonMethodX. The test each of the MethodForConditionX & SomeCommonMethodX in isolation and pass in a stub for TheBigMethod which validates that MethodForConditionX is called with value Z.

Edit: You could also make the methods virtual if you don't want to use an interface.


A bit late to the game here, but I would concur that mixing test and production code is a big code smell to be avoided. Big methods in legacy code provide all sorts of issues. I would highly recommend reading Michael Feather's Working Effectively with Legacy Code. It's all about dealing with the myriad of problems encountered in legacy code and how to deal with them.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜