2010-06-10 5 views
5

Me burlé de un par de métodos de mi capa de acceso a datos, pero en algunos métodos se establece el valor de un parámetro de salida de SQL. ¿Cómo puedo burlar esto?Parámetro de salida de SQL burlón

Método:

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); 

que imita (He intentado utilizar "OutRef", pero que no funciona):

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

Pero eso no funcionó. Cuando ejecuto el SP GetUser, se establece el valor param return, pero no tengo idea de cómo simular esto

+0

Intente utilizar IDbParameter sobre SqlParameter cuando sea posible, entonces se puede burlar al contenido de su corazón. –

Respuesta

2

Creo que eres yendo sobre esto de la manera incorrecta. Su interfaz DAL debe tener este aspecto:

/// <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); 
} 

La abstracción DAL ahora oculta el hecho de que se utiliza un procedimiento almacenado. De hecho, el DAL podría no ser siquiera una base de datos: podría ser un archivo de texto en disco, un servicio web, un simulacro o cualquier otra cosa.

Mocking el DAL para probar el código que utiliza el DAL ahora se vuelve trivial. He elegido el view model (también conocido como presentation model) de una pantalla de inicio de sesión como el sistema que se está probando en estos ejemplos:

[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

No creo que pueda burlarse, porque es un SqlParameter normal (clase concreta), y no es un parámetro out/ref en .Net sentido. Lo que me gustaría tratar es simplemente para establecer el valor del parámetro en la llamada burlado a dal (No he comprobado la sintaxis, pero estoy seguro de que usted consigue la idea):

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

Apagué esto usando el método "WhenCalled".

En mi código (para probar) primero creo la conexión y el comando y agrego tres parámetros, el tercero de los cuales es mi parámetro de salida. Luego llamo a "ExecuteCommand" en esto ... No voy a revisar el código porque creo que es bastante estándar (ExecuteCommand toma el objeto de comando como su parámetro).

En mi prueba, creo un trozo de mi servicio de datos SQL y programarlo para que este establece el valor del parámetro:

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 respuesta es probablemente un poco tarde para su proyecto, pero espero que esto ayuda a alguien ...

Griff

Cuestiones relacionadas