Su pregunta era sobre en qué se diferencia el marco de MS Fakes de NMock y parece que las otras respuestas han resuelto algo de eso, pero aquí hay más información sobre en qué se parecen y en qué se diferencian. NMock también es similar a RhinoMocks y Moq, así que los estoy agrupando con NMock.
Hay 3 diferencias principales que veo de inmediato entre NMock / RhinoMocks / Moq y MS Fakes Framework:
El marco de falsificaciones de MS utiliza código generado, al igual que Accessors en versiones anteriores de Visual Studio en lugar de tipos genéricos. Cuando desee utilizar el marco de falsificaciones para una dependencia, agregue el ensamblado que contiene la dependencia a las referencias del proyecto de prueba y luego haga clic derecho sobre él para generar los dobles de prueba (stubs o shims). Luego, cuando está probando, en realidad está utilizando estas clases generadas. NMock usa genéricos para lograr lo mismo (es decir IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()
). En mi opinión, el enfoque del marco de MS Fakes inhibe la navegación de código y la refactorización desde dentro de las pruebas, ya que en realidad está trabajando contra una clase generada, no su interfaz real.
El marco de falsificaciones de MS proporciona stubs y moles (shims), mientras que NMock, RhinoMocks y Moq proporcionan stubs y simulaciones . Realmente no entiendo la decisión de MS de no incluir simulacros y, personalmente, no soy un fanático de los lunares por las razones que se describen a continuación.
Con el marco de falsificaciones de MS, proporciona una implementación alternativa de los métodos que desea apuntar. Dentro de estas implementaciones alternativas, puede especificar los valores de retorno y realizar un seguimiento de la información sobre cómo o si se llamó al método. Con NMock, RhinoMocks y Moq, usted genera un objeto simulado y luego usa ese objeto para especificar valores de retorno stubped o para rastrear interacciones (si los métodos fueron llamados y cómo). Encuentro el enfoque de las falsificaciones de EM más complejo y menos expresivo.
Para aclarar la diferencia en lo que proporcionan los marcos: NMock, RhinoMocks y Moq proporcionan dos tipos de dobles de prueba (stubs y simulacros). El marco de falsificaciones proporciona talones y topos (los llaman calzas), y desafortunadamente no incluye simulaciones. Para comprender las diferencias y similitudes entre NMock y MS Fakes, es útil comprender cuáles son estos diferentes tipos de dobles de prueba:
Stubs: stubs se utilizan cuando necesita proporcionar valores para métodos o propiedades que se le solicitarán a su prueba duplicados por el método bajo prueba. Por ejemplo, cuando mi método bajo prueba llama al método DoesStudentExist () del doble de prueba IStudentRepository, quiero que devuelva verdadero.
La idea de los stubs en NMock y MS fakes es la misma, pero con NMock harías algo como esto:
Stub.On(mockStudentRepository).Method("DoesStudentExist").Will(Return.Value(true));
Y con MSFakes harías algo como esto:
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() // Generated by Fakes.
{
DoesStudentExistInt32 = (studentId) => { return new Student(); }
};
Observe que en el ejemplo de MS Fakes crea una implementación completamente nueva para el método DoesStudentExist (tenga en cuenta que se llama DoesStudentExistInt32 porque el marco de falsificaciones agrega los tipos de datos de parámetros a los nombres de los métodos cuando genera los objetos stub, creo que esto oscurece la claridad de los exámenes). Para ser honesto, la implementación de NMock también me molesta porque usa una cadena para identificar el nombre del método. (Perdóneme si he entendido mal cómo se pretende usar NMock). Este enfoque realmente inhibe la refactorización y por este motivo recomiendo encarecidamente RhinoMocks o Moq sobre NMock.
Simulacros: los simulacros se utilizan para verificar la interacción entre su método bajo prueba y sus dependencias. Con NMock, puede hacer esto estableciendo expectativas similares a esto:
Expect.Once.On(mockStudentRepository).Method("Find").With(123);
Esta es otra razón por la que preferiría RhinoMocks y Moq sobre NMock, NMock usa el estilo de expectativa anterior, mientras que RhinoMocks y Moq admiten el enfoque Arrange / Act / Assert en el que especifica las interacciones esperadas como afirmaciones al final de la prueba de esta manera. :
stubStudentRepository.AssertWasCalled( x => x.Find(123));
Nuevamente, tenga en cuenta que RhinoMocks utiliza una lambda en lugar de una cadena para identificar el método. El marco de ms fakes no proporciona simulaciones en absoluto. Esto significa que en sus implementaciones stub out (consulte la descripción de stubs arriba) debe establecer variables que luego verifique que se hayan configurado correctamente. Eso se vería algo así:
bool wasFindCalled = false;
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository()
{
DoesStudentExistInt32 = (studentId) =>
{
wasFindCalled = true;
return new Student();
}
};
classUnderTest.MethodUnderTest();
Assert.IsTrue(wasFindCalled);
Encuentro que este enfoque es un poco complicado, ya que debe rastrear la llamada en el código auxiliar y luego afirmarla más adelante en la prueba. Encuentro que los ejemplos NMock, y especialmente RhinoMocks, son más expresivos.
Moles (Shims): Para ser sincero, no me gustan los lunares, debido a su potencial de mal uso. Una de las cosas que me gustan tanto de las pruebas unitarias (y TDD en particular) es que probar su código le ayuda a comprender dónde ha escrito código deficiente. Esto se debe a que es difícil probar un código mal escrito. Esto no es cierto cuando se usan lunares porque en realidad los lunares están diseñados para permitirle realizar pruebas contra dependencias que no se inyectan o para probar métodos privados. Funcionan de manera similar a los stubs, excepto que usa un ShimsContext como este:
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet = () => { return new DateTime(fixedYear, 1, 1); };
}
Mi preocupación con las calzas es que la gente comenzará a verlas como "una forma más fácil de realizar pruebas unitarias" porque no te obliga a escribir código de la manera que deberías. Para una descripción más completa de este concepto, vea esta publicación mía:
Para obtener más información sobre algunas preocupaciones relacionadas con los marcos falsos, consulte estas publicaciones:
Si está interesado en aprender RhinoMocks, aquí hay un video de capacitación de Pluralsight (divulgación completa: escribí este curso y recibo regalías por las vistas, pero creo que se aplica a esta discusión, así que lo incluyo aquí):