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
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
Hi!

MyService class has a private fields a, b and c of various types and db of dynamic type MyDatabase (that implements IDatabase interface), and creates the objects in the constructor using an IOC container. Also the class has private method InnerCheck and public method DoUsefulThing, that I'd like to test:

public class MyService
{
   private IA a;
   private IB b;
   private IC c;
   private IDatabase db;

   public MyService()
   {
      a = ioc_container.Resolve<IA>();
      b = ioc_container.Resolve<IB>();
      c = ioc_container.Resolve<IC>();
      db = ioc_container.Resolve<IDatabase>();
   }

   public Result DoUsefulThing(string login, string data)
   {
      var ud = (UserData) db.Users_getUserData(login);
      if (ud.Uid != default(Guid))
      {
         if (InnerCheck(ud, data))
         {
            ///////////////////////////////
            // perform useful thing here //
            ///////////////////////////////
            return new Result(ResultCode.Ok, "");
         }
         return new Result(ResultCode.MethodFailed, "inner check failed");
      }
      return new Result(ResultCode.LoginFailedError, "user does not exist");
   }

   private bool InnerCheck(UserData ud, string data)
   {
      // for now it doesn't matter
      return new Random().Next(2) == 0;
   }
}

My variant of the test is the following:
[Test]
public void TheClass_test()
{
   var r = new UserData(new Guid("9763A087-9971-4098-A21D-46DA3C71EC01"));
   
   // arrange
   var db = Isolate.Fake.Instance<MyDatabase>(Members.CallOriginal);
   Isolate.WhenCalled(() => db.Users_getUserData(login)).WillReturn(r);
   Isolate.Swap.NextInstance<MyDatabase>().With(db);

   // act
   // In order to call the constructor explicitely I have to create
   // the object here, all the fields are normally initialized, and
   // typemock magic makes db field behave as in arrange
   // "section" above
   var ms = new MyService();

   // arrange again :-)
   Isolate.NonPublic.WhenCalled(ms, "InnerCheck").WillReturn(false); // !!!
   
   // act again :-)
   var result = ms.DoUsefulThing(login, "useful-data");

   // assert
   Assert.AreEqual(result, new Result(ResultCode.MethodFailed, "inner check failed"));
}

But I get the following exception in the string denoted "!!!"
TypeMock.TypeMockException: 
*** No method with name .ctor>b__0 in type MyService exists.


Hence, let me ask 2 questions:
1. What does the exception mean?
2. How to write the test in canonical AAA form?

Thank you in advance.
asked by tinynick (1.2k points)

5 Answers

0 votes
Hi,

It's a bit of a problem to reproduce with all the types you're using. Taking into account you're also invoking the IoC container, instead of faking the IDatabase instead. If you can reproduce a solution that would be great, I'd write a separate email.

As for your questions:
1. There's probably a bug somewhere. You should not get this exception, either something we didn't think of, or the message should be clear of what happened.

2. You're doing fine. What I would do instead of creating a fake MyDatabase, create an IDatabase instead. You are trying to replace the next MyDatabase, when in fact, you can fake the container and returned an IDatabase object. So you wouldn't need to swap a future value, just return the IDatabase.

As I said, I'll write you a separate mail regarding reproducing this.

Thanks
answered by gilz (14.5k points)
0 votes
Hi Nick,

I'm having troubles getting an email to you. Please send the solution to support at typemock dot com.

Thanks
answered by gilz (14.5k points)
0 votes
My attempt to create minimal example to reproduce the exception:
public struct UserSession {}

public class SessionContext<T>
{
   public Action<T> OnTimeout { get; set; }
}

public class MyService
{
   private readonly SessionContext<UserSession> snc;
   private readonly object session_lock = new object();

   public MyService()
   {
      snc = new SessionContext<UserSession>();
      snc.OnTimeout = delegate(UserSession s)
      {
         lock (session_lock)
         {
            Console.WriteLine("timeout");
         }
      };
   }

   public Result Login(string version, string login, string password)
   {
      if (!CheckLoginCount(login))
         return new Result(ResultCode.LoginFailedError, "");
      return new Result(ResultCode.Ok, "");
   }

   public bool CheckLoginCount(string login)
   {
      return new Random().Next(2) == 0;
   }
}

The test is
[Test]
public void MyService_test()
{
   // act
   var ss = new MyService();

   // arrange
   Isolate.NonPublic.WhenCalled(ss, "CheckLoginCount").WillReturn(false);
   
   // act again :-)
   var result = ss.Login("0.1", login, password);

   // assert
   Assert.AreEqual(result, new Result(ResultCode.MethodFailed, "inner check failed"));

}

and I get the following exception:
TypeMock.TypeMockException: 
*** No method with name .ctor>b__0 in type Test.MyService exists.
at cz.b(Type A_0, String A_1)
at cz.c(Type A_0, String A_1)
at TypeMock.Mock.a(String A_0, Object A_1, Boolean A_2, Boolean A_3, Int32 A_4, Type[] A_5)
at TypeMock.Mock.a(String A_0, Object A_1, Boolean A_2, Boolean A_3, Type[] A_4)
at TypeMock.Mock.AlwaysCallOriginal(String method, Type[] genericTypes)
at TypeMock.MockManager.b(Mock A_0, BindingFlags A_1)
at TypeMock.MockManager.b(Object A_0, String A_1)
at ev..ctor(Object A_0, String A_1)
at b3..ctor(Object A_0, String A_1)
at ah.b(Object A_0, String A_1)
at OffSiteBoxTest.Basic.MyService_test() in Basic.cs: line 196


I hope it will help :-)

Best regards,
Nick.
answered by tinynick (1.2k points)
0 votes
Hi Nick,

Thanks for posting the example code. The issue you are facing is due to a bug in the recent Isolator versions handling anonymous delegates in AAA. The anonymous delegate in the MyService c'tor is causing this crash.

This bug is now fixed and will be released in our upcoming version in a few days. I will send you an email when the version is out to make sure this resolves the issue.

Thanks,
Doron
Typemock support
answered by doron (17.2k points)
0 votes
This issue has been fixed in Isolator version 5.2.0
answered by dhelper (11.9k points)
...