2010-09-24 10 views
5

Tengo el siguiente método de firma en mi iterface:NSustituye los parámetros de ref de soporte?

void SetItem(ref AddressItem item); 

hago una restricción de parámetros de esta manera:

IAddAddressForm form = Substitute.For<IAddAddressForm>(); 
AddressItem item = null; 
form.SetItem(Arg.Is(item)); 

Pero eso no funciona debido a que el árbitro. Si retiro el ref, funciona bien. Pero necesito pasar por referencia aquí.

¿Alguna idea de cómo conseguir esto?

Nota al costado: Mi objetivo final es lanzar una excepción en SetItem si el valor pasado es nulo. ¡Si puedes ayudar con eso, entonces obtienes puntos extra!

+0

Tengo mucha curiosidad por saber por qué debe usar 'ref' aquí. ¿Puede usted explicar por favor? –

+0

Bueno, estoy haciendo un proyecto de muestra para capacitar a mi departamento de TI en pruebas unitarias usando NSubstitute y Moles. Como parte de esto quiero molestar a Linq-To-SQL. Para hacer eso, necesitaba hacer algunas actualizaciones a un objeto devuelto por una consulta de Linq a sql. Descubrí que si no pasaba el objeto con el 'ref ', entonces la actualización fallaba (porque ya no reconocía el objeto como el consultado). Esta puede no ser la" mejor práctica "para linq a sql, pero yo soy pruebas de unidad de entrenamiento, no Linq. – Vaccano

+0

Puede ver la pregunta/respuesta que hace que mi código sea así aquí: http://stackoverflow.com/questions/3766417/save-changes-in-linq-to-sql/3770482#3770482 – Vaccano

Respuesta

10

NSustituir no tiene soporte directo para los parámetros de referencia de concordancia arg, pero en general funcionará con ellos bien.

Voy a suponer que tiene que usar ref como se indica en su pregunta, pero obviamente si puede evitar ref su API será más simple, al igual que la prueba (independientemente de los marcos que utilice).

En respuesta a su pregunta inmediata, puede pasar una referencia mediante la actualización de su segundo ejemplo de código a:

form.SetItem(ref item); 

Para su nota al margen, asegurarse de que no está tratando de empujar demasiado el comportamiento en su sustituto . He descubierto que cada vez que hago esto, es un signo que necesito para simplificar la comunicación entre la clase que estoy probando y sus dependencias. (O si realmente necesito mucha lógica en un objeto falso, entregaré el código uno en lugar de generarlo; a menudo puede ser más simple)

Hay varias maneras de hacer que esta llamada genere una excepción :

form.When(x => x.SetItem(ref item)).Do(x => { throw new ArgumentNullException(); }); 

Esto emitirá una excepción solo cuando se invoque con una referencia nula. También puede agregar este comportamiento de forma selectiva según el argumento pasado, aunque desaconsejaré esto ya que probablemente sea un signo de que está presionando demasiado a su sustituto.

form.WhenForAnyArgs(x => x.SetItem(ref item)) 
    .Do(x => { 
     if (x[0] == null) 
      throw new ArgumentNullException(); 
    }); 

Por último, si lo que desea es comprobar que la clase que se está probando responde correctamente cuando se produce una excepción IAddAddressForm nula arg, probablemente me acaba de hacer esto:

form 
    .WhenForAnyArgs(x => x.SetItem(ref item)) 
    .Do(x => { throw new ArgumentNullException(); }); 

De esa manera usted don Realmente no le importa cuál es el argumento, solo quiere asegurarse de que el código que está probando reaccione a este caso correctamente.

Espero que esto ayude.

Nota al margen:

Si desea utilizar una matcher arg (como Arg.Any<AddressItem>()) para un argumento out o ref tendrá que definirlo fuera de la propia llamada (esto puede ser un error poco propensa : deberá asegurarse de definir los mezcladores en el mismo orden en que aparecerán en la llamada):

 IAddAddressForm form = Substitute.For<IAddAddressForm>(); 
     AddressItem item = Arg.Is<AddressItem>(y => y.Number == 14); 
     form 
      .When(x => x.SetItem(ref item)) 
      .Do(x => { throw new ArgumentNullException(); }); 
     var address = new AddressItem { Number = 14 }; 
     form.SetItem(ref address); 
+0

¡Muy completa respuesta! Gracias un montón. Puede parecer que estoy haciendo mucho con mis sustitutos, pero eso se debe a que estoy entrenando para mis compañeros de trabajo y mis ejemplos son un poco artificiales. – Vaccano

Cuestiones relacionadas