chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
Hi All,

I'm relatively new to the TypeMock scene and I am having an issue Isolating a call to a static function in a class that has a static constructor. I'm fairly certain it's due to the static c'tor. The error I get is as follows, the particularly interesting spots are:

TypeMock.CannotEvaluateWhileRecordingException:
*** Cannot evaluate methods inside a recording block


and a little bit further down:
System.TypeInitializationException: The type initializer for 'Comkt.Web.Estara.EstaraHelper' threw an exception.
at Comkt.Web.Estara.EstaraHelper.GetCoreJS(EstaraPageCategory templateCategory)



TypeMock.CannotEvaluateWhileRecordingException: 
*** Cannot evaluate methods inside a recording block
at TypeMock.MockManager.a(String A_0, String A_1, Object A_2, Object A_3, Boolean A_4, Object[] A_5)
at TypeMock.InternalMockManager.getReturn(Object that, String typeName, String methodName, Object methodParameters, Boolean isInjected, Object p1)
at NetUtils.Legacy.LegacyUtil.GetConfig(String configName) in Util.cs: line 13
at Comkt.Web.Estara.EstaraHelper..cctor() in EstaraHelper.cs: line 35 
System.TypeInitializationException: The type initializer for 'Comkt.Web.Estara.EstaraHelper' threw an exception.
at Comkt.Web.Estara.EstaraHelper.GetCoreJS(EstaraPageCategory templateCategory)
at CMWebTests.Estara.BaseEstaraControllerTests.<GetEstaraCoreScript_Test>b__0() in BaseEstaraControllerTests.cs: line 89
at TypeMock.MockManager.a(String A_0, String A_1, Object A_2, Object A_3, Boolean A_4, Object[] A_5)
at TypeMock.InternalMockManager.getReturn(Object that, String typeName, String methodName, Object methodParameters, Boolean isInjected)
at CMWebTests.Estara.BaseEstaraControllerTests.GetEstaraCoreScript_Test() in BaseEstaraControllerTests.cs: line 78


Pertinents parts of class I'd like to mock calls to/from:
public class EstaraHelper {
   private static bool estaraIntegrationOn;
   private static string coreScriptUrl;
   private static string accountId;
   private static string buttonImageUrl;

   private static bool EstaraIntegrationOn {
      get { return estaraIntegrationOn; }
   }

   private static string CoreScriptUrl {
      get { return coreScriptUrl;   }
   }
   
   private static string AccountId {
      get { return accountId;   }
   }

   private static string ButtonImageUrl {
      get { return buttonImageUrl; }
   }

   static EstaraHelper() {
      string estaraIntegrationSetting = LegacyUtil.GetConfig("EstaraIntegrationOn"); 
      estaraIntegrationOn = estaraIntegrationSetting.ToLower().Equals("y");   
      accountId = LegacyUtil.GetRequiredConfig("EstaraAccountId");
      coreScriptUrl = LegacyUtil.GetRequiredConfig("EstaraCoreScriptURL");
      buttonImageUrl = LegacyUtil.GetRequiredConfig("EstaraPttButtonUrl");
   }


   ...

   //FUNC I'D LIKE TO FORCE THE RESULTS FROM
   public static string GetCoreJS(EstaraPageCategory templateCategory) {
      if (EstaraIntegrationOn) {            
         return PutTogetherCoreJS(templateCategory);
      }
      else {
         return String.Empty;
      }
   }
}


A simple NUnit test causing the error:

[Test, Isolated]
public void GetEstaraCoreScript_Test() {
   const string testCoreJsScript = "My Test Core JS Script";
   const long testPageViewEventIt = 9999;
   const EstaraPageCategory testPageCategory = EstaraPageCategory.AutoAspx;

   MockEstaraController mockEstaraController = new MockEstaraController(testPageCategory, testPageViewEventIt);
   Isolate.WhenCalled(() => EstaraHelper.GetCoreJS(EstaraPageCategory.AutoAspx)).WillReturn(testCoreJsScript);


   //function under test
   string result = mockEstaraController.GetEstaraCoreScript();

   Assert.AreEqual(testCoreJsScript, result);
}


The static c'tor in question is relatively benign, just setting some private class variables from the configuration system, I could change the public accessors to them to lazy initialize, but I'd rather not have to change the class under test.

Any thoughts?

Thanks in advance for the help!
asked by johnminadeo (1.3k points)

7 Answers

0 votes
Hi John, and welcome to Isolator!

A problem I can see in the test code is that the WhenCalled() instruction has a nested chain - two calls within one another. This is currently unsupported by Isolator. To fix this, you should turn this:
Isolate.WhenCalled(() => EstaraHelper.GetCoreJS(EstaraPageCategory.AutoAspx)).WillReturn(testCoreJsScript);

Into this:
var autoAspx = EstaraPageCategory.AutoAspx;
Isolate.WhenCalled(() => EstaraHelper.GetCoreJS(autoAspx)).WillReturn(testCoreJsScript);


You may also want to fake static calls on EstaraPageCategory, depending on your isolation needs.

Let me know if this helps,
Doron
Typemock Support
answered by doron (17.2k points)
0 votes
As you are ignoring the argument entirely - which is great as it keeps the test clean and not fragile
- simply pass a null

Isolate.WhenCalled(() => EstaraHelper.GetCoreJS(null)).WillReturn(testCoreJsScript); 
answered by eli (5.7k points)
0 votes
Thanks, Eli - good catch :oops:
answered by doron (17.2k points)
0 votes
Hmm, i tried replacing the EstaraPageCategory.AutoAspx with null as Eli suggested since I am ignoring it. I am still getting the TypeInitialization Exception.

FWIW, EstaraPageCategory is an enum and EstaraPageCategory.AutoAspx is the first item in it. Does the nested call chain issue still apply? I can't say I fully understand the nested call chain problem.

In my first issue (the one I posted some code for in my question), I ended up refactoring the code under test to use lazy initialization instead of the static c'tor and the error stopped.

In fact, another class I started writing a test for has a static c'tor and I'm getting the same error.

Any other thoughts?

Thanks again!
answered by johnminadeo (1.3k points)
0 votes
Well I came home and made a simple test and of course TypeMock had no issues with the static c'tor class or member. Though I am not sure why the null parameter didn't help in the prior advice.

:oops:
answered by johnminadeo (1.3k points)
0 votes
Hi John

The null parameter should not make any difference in the test code since the method "GetCoreJS" is faked.
The null parameter will just make the code shorter. In your case I'm not sure it's possible since the argument is an enum value.

I'm not clear about your tests status at the moment, are all tests passing?
answered by ohad (35.4k points)
0 votes
Well I worked around both problems I had by modifying the code under test to give work easier. And the problem was not a static c'tor as I had thought as I created a small project to test it at home and was able to mock it no problem. Unfortunately, I will not have access to the codebase until the end of the month.

At this point I believe the issue to be my own fault due to inexperience with the APIs... I do appreciate the help! I will re-open this thread when I can get to the code again.

Again, Thanks!
answered by johnminadeo (1.3k points)
...