2010-06-10 18 views
5

Ho preso in giro un paio di metodi del mio livello di accesso ai dati, ma in alcuni metodi è impostato il valore di un parametro di output SQL. Come posso deridere questo?Mocking Parametro di output SQL

Metodo:

var wrappedParameters = new SqlParameter[3]; 
      wrappedParameters[0] = new SqlParameter("@username",username); 
      wrappedParameters[1] = new SqlParameter("@password",password); 
      wrappedParameters[2] = new SqlParameter("returnValue",SqlDbType.Int) { Direction =ParameterDirection.ReturnValue }; 

      dal.ExecuteUsingStoredProcedure("GetUser", wrappedParameters); 

Mocking (ho provato con "OutRef", ma che non funziona):

using (mocks.Record()) 
     { 
      Expect.Call(dal.ExecuteUsingStoredProcedure("",> null)).Return(true).IgnoreArguments().OutRef(1); 
     } 

Ma che non ha funzionato. Quando esagero SP GetUser viene impostato il valore di ritorno param, ma non ho idea di come deridere questo

+0

Provare a usare IDbParameter oltre SqlParameter quando possibile, allora si può prendere in giro al contenuto del vostro cuore. –

risposta

2

Penso che tu sia andare su questo nel modo sbagliato. L'interfaccia DAL dovrebbe essere simile a questa:

/// <summary> 
/// Models a service which holds the user information. 
/// </summary> 
public interface IUserRepository 
{ 
    /// <summary> 
    /// Gets the user with the given name, or <c>null</c> if no user with 
    /// that name and password exists. 
    /// </summary> 
    /// <exception cref="IOException"> 
    /// An I/O problem occurred while accessing the repository. 
    /// </exception> 
    User TryGetUser(string name, string password); 
} 

L'astrazione DAL ora nasconde il fatto che viene utilizzata una stored procedure. In effetti, il DAL potrebbe non essere nemmeno un database: potrebbe essere un file di testo su disco, un webservice, una finta o qualsiasi altra cosa.

Mocking del DAL per testare il codice che utilizza il DAL ora diventa banale. Ho scelto il view model (aka presentation model) di una schermata di login come il sistema in prova in questi esempi:

[Test] 
public void Login_sets_user_and_goes_to_main_screen_when_TryGetUser_not_null() 
{ 
    var userRepositoryStub = MockRepository.GenerateStub<IUserRepository>(); 
    var user = new User(...); 
    userRepositoryStub.Stub(x=>x.GetUserByName("foo","bar")).Return(user); 
    var sessionStub = MockRepository.GenerateStub<ISession>(); 
    var loginScreenViewModel = 
     new LoginScreenViewModel(sessionStub, userRepositoryStub); 

    loginScreenViewModel.UserName = "foo"; 
    loginScreenViewModel.Password = "bar"; 
    loginScreenViewModel.Login(); 

    userRepositoryStub.AssertWasCalled(x=>x.TryGetUser("foo","bar")); 
    sessionStub.AssertWasCalled(x=>x.ShowMainScreen()); 
    Assert.AreEqual(user, session.User); 
} 

.

[Test] 
public void Login_shows_error_when_TryGetUser_returns_null() 
{ 
    var userRepositoryStub = MockRepository.GenerateStub<IUserRepository>(); 
    var sessionStub = MockRepository.GenerateStub<ISession>(); 
    var loginScreenViewModel = 
     new LoginScreenViewModel(sessionStub, userRepositoryStub); 

    loginScreenViewModel.UserName = "foo"; 
    loginScreenViewModel.Password = "bar"; 
    loginScreenViewModel.Login(); 

    Assert.AreEqual(loginScreenViewModel.Error, 
     "User 'foo' does not exist or password is incorrect")); 
    userRepositoryStub.AssertWasCalled(x=>x.TryGetUser("foo","bar")); 
    sessionStub.AssertWasNotCalled(x=>x.ShowMainScreen()); 
    Assert.IsNull(session.User); 
} 
0

Non penso che si possa deriderlo, perché è un normale SqlParameter (classe concreta), e non è un parametro out/ref in .Net sense. Quello che vorrei provare è quello di impostare semplicemente il valore del parametro nella chiamata a deriso dal (non ho controllato la sintassi, ma sono sicuro che si ottiene l'idea):

using (mocks.Record()) 
     { 
      Expect.Call(dal.ExecuteUsingStoredProcedure("",null)).Return(true).IgnoreArguments().Do(x => wrappedParameters[2].Value = 1; true); 
     } 
0

Ho annullato questo utilizzando il metodo "WhenCalled".

Nel mio codice (da testare) prima creo la connessione e comando e aggiungo tre parametri, il terzo dei quali è il mio parametro di uscita. Quindi chiamo "ExecuteCommand" su questo ... Non passerò attraverso il codice per questo perché penso che sia abbastanza standard (ExecuteCommand prende l'oggetto comando come parametro).

Nella mia prova, creo uno stub per il mio servizio di dati di SQL e programmarlo in modo che tale imposta il valore del parametro:

var sqlService = MockRepository.GenerateStub<ISqlDataService>(); 
sqlService.Stub(s => s.ExecuteCommand(null)) 
    .IgnoreArguments() 
    .WhenCalled(s => ((SqlCommand)s.Arguments[0]).Parameters[2].Value = expectedValue) 
    .Return(0); 

La risposta è probabilmente un po 'tardi per il progetto, ma spero che questo aiuta qualcuno ...

Griff