Question

I'm new to unit testing with mocking.

I've have this method:

    virtual public bool Authenticate(
        Identity identity,
        out IdentityReference entityReference,
        out RightAssignment rights)
    {
        entityReference = null;
        rights = null;

        string passwordHash = identity.Passwd;

        string customerId;
        string userId;

        using (IScope scope = DataAccess.GetScope())
        {
            DA.eCheckResult result = DataAccess.Check(
                    scope,
                    identity.Domain,
                    identity.Login,
                    passwordHash,
                    identity.BranchIdentification,
                    identity.CustomerIdentification,
                    out customerId,
                    out userId);

            if (result == eCheckResult.cOK)
            {
                entityReference = new IdentityReference
                {
                    CustomerId = customerId,
                    UserId = userId
                };

                rights = DataAccess.GetRightAssignment(scope, userId);
            }

            return DA.eCheckResult.cOK == result;
        }
    }

DataAccess is an interface declared like this:

   public interface IAuthenticateDA : IDisposable
   {
       eCheckResult Check(
            IScope scope,
            string domain,
            string login,
            string passwordHash,
            string branchIdentification,
            string customerIdentification,
            out string customerId,
            out string userId);

        RightAssignment GetRightAssignment(IScope scope, string userId);

        /// <summary>
        /// Gets the scope of the underlying data accessor
        /// </summary>
        IScope GetScope();
   }

My current attempt at mocking, looks like this:

MockRepository mocks = new MockRepository();

IAuthenticateDA mockAuthenticateDA = mocks.StrictMock<IAuthenticateDA>();

string customerId;
string userId;

Expect.Call(mockAuthenticateDA.GetScope()).Return(null);
Expect.Call(mockAuthenticateDA.Check(
    null,
    "orgadata",
    "test",
    "test",
    "branch",
    "customer",
    out customerId,
    out userId)).Return(eCheckResult.cOK);
Expect.Call(mockAuthenticateDA.GetRightAssignment(null, "userId"))
    .Return(MockupDA.Rights);

And this is my error message:

Die Orgadata.Auth.TestUnits.ServiceTest.TestBLAuthenticate-Testmethode hat eine Ausnahme ausgelöst: System.InvalidOperationException: Previous method 'IAuthenticateDA.GetScope();' requires a return value or an exception to throw.
Ergebnis StackTrace:    
bei Rhino.Mocks.Impl.RecordMockState.AssertPreviousMethodIsClose()
   bei Rhino.Mocks.Impl.RecordMockState.MethodCall(IInvocation invocation, MethodInfo method, Object[] args)
   bei Rhino.Mocks.MockRepository.MethodCall(IInvocation invocation, Object proxy, MethodInfo method, Object[] args)
   bei Rhino.Mocks.Impl.Invocation.Actions.RegularInvocation.PerformAgainst(IInvocation invocation)
   bei Rhino.Mocks.Impl.RhinoInterceptor.Intercept(IInvocation invocation)
   bei Castle.DynamicProxy.AbstractInvocation.Proceed()
   bei Castle.Proxies.IAuthenticateDAProxy619e9a2b8594464d89e95c4149fb2ab3.IDisposable.Dispose()
   bei Microsoft.Practices.Unity.ContainerControlledLifetimeManager.Dispose(Boolean disposing) in c:\tfs\EL\V5-SL\UnityTemp\Compile\Unity\Unity\Src\Lifetime\ContainerControlledLifetimeManager.cs:Zeile 76.
   bei Microsoft.Practices.Unity.ContainerControlledLifetimeManager.Dispose() in c:\tfs\EL\V5-SL\UnityTemp\Compile\Unity\Unity\Src\Lifetime\ContainerControlledLifetimeManager.cs:Zeile 60.
   bei Microsoft.Practices.ObjectBuilder2.LifetimeContainer.Dispose(Boolean disposing) in c:\tfs\EL\V5-SL\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Lifetime\LifetimeContainer.cs:Zeile 103.
   bei Microsoft.Practices.ObjectBuilder2.LifetimeContainer.Dispose() in c:\tfs\EL\V5-SL\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Lifetime\LifetimeContainer.cs:Zeile 79.
   bei Microsoft.Practices.Unity.UnityContainer.Dispose(Boolean disposing) in c:\tfs\EL\V5-SL\UnityTemp\Compile\Unity\Unity\Src\UnityContainer.cs:Zeile 466.
   bei Microsoft.Practices.Unity.UnityContainer.Dispose() in c:\tfs\EL\V5-SL\UnityTemp\Compile\Unity\Unity\Src\UnityContainer.cs:Zeile 449.
   bei Orgadata.Framework.IoC.Unity.TransientContainerProvider.Dispose(Boolean disposing) in x:\sourcen\Services\Framework\Orgadata.Framework.IoC.Unity\TransientContainerProvider.cs:Zeile 101.
   bei Orgadata.Framework.IoC.Unity.TransientContainerProvider.Dispose() in x:\sourcen\Services\Framework\Orgadata.Framework.IoC.Unity\TransientContainerProvider.cs:Zeile 111.
   bei Orgadata.Auth.TestUnits.ServiceTest.TestBLAuthenticate() in x:\sourcen\Services\Authentification\Orgadata.Auth.TestUnits\ServiceTest.cs:Zeile 168.
Était-ce utile?

La solution

Rhino Mocks requires you to record your expectations, so you need to wrap them in a using block.

 using (mocks.Ordered())
 {
   Expect.Call(mockAuthenticateDA.GetScope)
         .Return(null);
   Expect.Call(() => mockAuthenticateDA.Check(
          null, "orgadata", "test", "test", "branch", "customer",
          out customerId, out userId))
         .Return(eCheckResult.cOK);
   Expect.Call(() => mockAuthenticateDA.GetRightAssignment(null, "userId"))
         .Return(MockupDA.Rights);
 }

 mocks.ReplayAll();

 using (mocks.Playback())
 {
      var result = testClass.Authenticate(identity, identityReference);
 }

Note ReplayAll is needed to explicitly mark the expectations as recorded, as mocks.Ordered() by itself doesn't begin recording. You could alternatively wrap the mocks.Ordered in an outer begin record using block and drop the ReplayAll:

 using (mocks.Record())
 {
   using (mocks.Ordered())
   {
     Expect.Call(mockAuthenticateDA.GetScope)
         .Return(null);
     Expect.Call(() => mockAuthenticateDA.Check(
          null, "orgadata", "test", "test", "branch", "customer",
          out customerId, out userId))
         .Return(eCheckResult.cOK);
     Expect.Call(() => mockAuthenticateDA.GetRightAssignment(null, "userId"))
         .Return(MockupDA.Rights);
   }
 }

 using (mocks.Playback())
 {
      var result = testClass.Authenticate(identity, identityReference);
 }

Autres conseils

This code shouldn't even compile.

Expect.Call requires an Action, so you want to do this:

Expect.Call(mockAuthenticateDA.GetScope)
      .Return(null);
Expect.Call(() => mockAuthenticateDA.Check(
                      null, "orgadata", "test", "test", "branch", "customer",
                      out customerId, out userId))
      .Return(eCheckResult.cOK);
Expect.Call(() => mockAuthenticateDA.GetRightAssignment(null, "userId"))
      .Return(MockupDA.Rights);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top