Aislar el código en pruebas con Microsoft FakesIsolate code under test with Microsoft Fakes

Microsoft Fakes ayuda a aislar el código que se está probando mediante la sustitución de otros elementos de la aplicación con código auxiliar o correcciones de compatibilidad (shim) .Microsoft Fakes helps you isolate the code you are testing by replacing other parts of the application with stubs or shims. Se trata de pequeños fragmentos de código que están bajo el control de las pruebas.These are small pieces of code that are under the control of your tests. Al aislar código para pruebas, sabe que, en caso de error, la causa está localizada ahí y no en alguna otra parte.By isolating your code for testing, you know that if the test fails, the cause is there and not somewhere else. El código auxiliar y las correcciones de compatibilidad (shims) también permiten probar el código aunque no funcionen otras partes de la aplicación todavía.Stubs and shims also let you test your code even if other parts of your application are not working yet.

Fakes tiene dos versiones:Fakes come in two flavors:

  • El código auxiliar reemplaza a una clase por un pequeño sustituto que implementa la misma interfaz.A stub replaces a class with a small substitute that implements the same interface. Para utilizar código auxiliar, tiene que diseñar la aplicación para que cada componente dependa únicamente de interfaces y no de otros componentes.To use stubs, you have to design your application so that each component depends only on interfaces, and not on other components. (Por "componente" se entiende una clase o grupo de clases diseñadas y actualizadas a la vez y que suelen estar contenidas en un ensamblado).(By "component" we mean a class or group of classes that are designed and updated together and typically contained in an assembly.)

  • Una corrección de compatibilidad (shim) modifica el código compilado de la aplicación en tiempo de ejecución para que, en lugar de realizar una llamada de método especificada, ejecute el código shim que proporciona la prueba.A shim modifies the compiled code of your application at run time so that instead of making a specified method call, it runs the shim code that your test provides. Las correcciones de compatibilidad (shims) se pueden usar para reemplazar las llamadas a ensamblados que no se pueden modificar, como los ensamblados .NET.Shims can be used to replace calls to assemblies that you cannot modify, such as .NET assemblies.

Fakes reemplaza otros componentes

RequisitosRequirements

  • Visual Studio EnterpriseVisual Studio Enterprise
  • Un proyecto de .NET FrameworkA .NET Framework project

Note

  • No se admiten los proyectos de .NET Standard..NET Standard projects are not supported.
  • La generación de perfiles con Visual Studio no está disponible para las pruebas que usan Microsoft Fakes.Profiling with Visual Studio is not available for tests that use Microsoft Fakes.

Elegir entre código auxiliar y corrección de compatibilidad (shim)Choose between stub and shim types

Normalmente, un proyecto de Visual Studio se consideraría un componente, porque esas clases se desarrollan y actualizan al mismo tiempo.Typically, you would consider a Visual Studio project to be a component, because you develop and update those classes at the same time. Puede considerar el uso de código auxiliar y correcciones de compatibilidad (shims) para las llamadas que el proyecto realice a otros proyectos de la solución o a otros ensamblados a los que el proyecto haga referencia.You would consider using stubs and shims for calls that the project makes to other projects in your solution, or to other assemblies that the project references.

Como directriz general, utilice código auxiliar para las llamadas dentro de la solución de Visual Studio y correcciones de compatibilidad (shims) para las llamadas a otros ensamblados a los que se hace referencia.As a general guide, use stubs for calls within your Visual Studio solution, and shims for calls to other referenced assemblies. El motivo es que, en su propia solución, es recomendable desacoplar los componentes definiendo las interfaces de la manera que el procesamiento con stub requiere.This is because within your own solution it is good practice to decouple the components by defining interfaces in the way that stubbing requires. Pero los ensamblados externos, como System.dll, no se proporcionan normalmente con definiciones de interfaz independientes, por lo que en su lugar se deben utilizar correcciones de compatibilidad (shims).But external assemblies such as System.dll typically are not provided with separate interface definitions, so you must use shims instead.

Otras consideraciones son:Other considerations are:

Rendimiento.Performance. Las correcciones de compatibilidad (shims) se ejecutan más lentamente porque reescriben el código en tiempo de ejecución.Shims run slower because they rewrite your code at run time. El código auxiliar no tiene esta sobrecarga de rendimiento y es tan rápido como los métodos virtuales.Stubs do not have this performance overhead and are as fast as virtual methods can go.

Métodos estáticos, tipos sellados.Static methods, sealed types. Solo se puede utilizar código auxiliar para implementar interfaces.You can only use stubs to implement interfaces. Por consiguiente, los tipos de código auxiliar no pueden utilizarse para los métodos estáticos, métodos no virtuales, métodos virtuales sellados, métodos de tipos sellados, etcétera.Therefore, stub types cannot be used for static methods, non-virtual methods, sealed virtual methods, methods in sealed types, and so on.

Tipos internos.Internal types. El código auxiliar y las correcciones de compatibilidad (shims) se pueden usar con los tipos internos que se hacen accesibles mediante el atributo de ensamblado InternalsVisibleToAttribute.Both stubs and shims can be used with internal types that are made accessible by using the assembly attribute InternalsVisibleToAttribute.

Métodos privados.Private methods. Las correcciones de compatibilidad (shims) pueden reemplazar llamadas a métodos privados si todos los tipos en la firma de método están visibles.Shims can replace calls to private methods if all the types on the method signature are visible. El código auxiliar solo puede reemplazar métodos visibles.Stubs can only replace visible methods.

Interfaces y métodos abstractos.Interfaces and abstract methods. El código auxiliar proporciona implementaciones de interfaces y métodos abstractos que se pueden utilizar en la prueba.Stubs provide implementations of interfaces and abstract methods that can be used in testing. Las correcciones de compatibilidad (shims) no pueden instrumentar interfaces y métodos abstractos, porque no tienen cuerpos de método.Shims can't instrument interfaces and abstract methods, because they don't have method bodies.

Por lo general, nosotros recomendamos que se utilicen tipos de código auxiliar para aislar las dependencias del código base.In general, we recommend that you use stub types to isolate from dependencies within your codebase. Esto se puede conseguir ocultando los componentes en interfaces.You can do this by hiding the components behind interfaces. Los tipos de corrección de compatibilidad (shim) pueden utilizarse para aislar los componentes de terceros que no proporcionan API comprobables.Shim types can be used to isolate from third-party components that do not provide a testable API.

Introducción a los stubGet started with stubs

Para obtener una descripción más detallada, vea Usar stubs para aislar las partes de la aplicación entre sí para las pruebas unitarias.For a more detailed description, see Use stubs to isolate parts of your application from each other for unit testing.

  1. Inyectar interfacesInject interfaces

    Para utilizar código auxiliar, tiene que escribir el código que desea probar de manera que no mencione clases en otro componente de la aplicación.To use stubs, you have to write the code you want to test in such a way that it does not explicitly mention classes in another component of your application. Por "componente" se entiende una clase o clases que se desarrollan y se actualizan juntas, y que normalmente están contenidas en un proyecto de Visual Studio.By "component" we mean a class or classes that are developed and updated together, and typically contained in one Visual Studio project. Las variables y los parámetros que se deben declarar con interfaces e instancias de otros componentes deben pasarse en o crearse mediante un generador.Variables and parameters should be declared by using interfaces and instances of other components should be passed in or created by using a factory. Por ejemplo, si StockFeed es una clase de otro componente de la aplicación, se consideraría erróneo:For example, if StockFeed is a class in another component of the application, then this would be considered bad:

    return (new StockFeed()).GetSharePrice("COOO"); // Bad

    En su lugar, defina una interfaz que el otro componente pueda implementar y que también pueda implementar el código auxiliar con fines de evaluación:Instead, define an interface that can be implemented by the other component, and which can also be implemented by a stub for test purposes:

    public int GetContosoPrice(IStockFeed feed) => feed.GetSharePrice("COOO");
    
    Public Function GetContosoPrice(feed As IStockFeed) As Integer
     Return feed.GetSharePrice("COOO")
    End Function
    
    
  2. Agregar un ensamblado de FakesAdd Fakes Assembly

    1. En el Explorador de soluciones, expanda la lista de referencia del proyecto de prueba.In Solution Explorer, expand the test project's reference list. Si está trabajando en Visual Basic, debe seleccionar Mostrar todos los archivos para ver la lista de referencia.If you are working in Visual Basic, you must choose Show All Files in order to see the reference list.

    2. Seleccione la referencia al ensamblado donde se define la interfaz (por ejemplo IStockFeed).Select the reference to the assembly in which the interface (for example IStockFeed) is defined. En el menú contextual de esta referencia, seleccione Agregar ensamblado de Fakes.On the shortcut menu of this reference, choose Add Fakes Assembly.

    3. Recompilar la solución.Rebuild the solution.

  3. En las pruebas, cree instancias de código auxiliar y proporcione código para sus métodos:In your tests, construct instances of the stub and provide code for its methods:

    [TestClass]
    class TestStockAnalyzer
    {
        [TestMethod]
        public void TestContosoStockPrice()
        {
          // Arrange:
    
            // Create the fake stockFeed:
            IStockFeed stockFeed =
                 new StockAnalysis.Fakes.StubIStockFeed() // Generated by Fakes.
                     {
                         // Define each method:
                         // Name is original name + parameter types:
                         GetSharePriceString = (company) => { return 1234; }
                     };
    
            // In the completed application, stockFeed would be a real one:
            var componentUnderTest = new StockAnalyzer(stockFeed);
    
          // Act:
            int actualValue = componentUnderTest.GetContosoPrice();
    
          // Assert:
            Assert.AreEqual(1234, actualValue);
        }
        ...
    }
    
    <TestClass()> _
    Class TestStockAnalyzer
    
        <TestMethod()> _
        Public Sub TestContosoStockPrice()
            ' Arrange:
            ' Create the fake stockFeed:
            Dim stockFeed As New StockAnalysis.Fakes.StubIStockFeed
            With stockFeed
                .GetSharePriceString = Function(company)
                                           Return 1234
                                       End Function
            End With
            ' In the completed application, stockFeed would be a real one:
            Dim componentUnderTest As New StockAnalyzer(stockFeed)
            ' Act:
            Dim actualValue As Integer = componentUnderTest.GetContosoPrice
            ' Assert:
            Assert.AreEqual(1234, actualValue)
        End Sub
    End Class
    
    

    El toque mágico aquí lo pone la clase StubIStockFeed.The special piece of magic here is the class StubIStockFeed. Para cada interfaz del ensamblado al que se hace referencia, el mecanismo de Microsoft Fakes genera una clase de código auxiliar.For every interface in the referenced assembly, the Microsoft Fakes mechanism generates a stub class. El nombre de la clase de código auxiliar se deriva del nombre de la interfaz, con "Fakes.Stub" como prefijo y los nombres de los tipos de parámetros anexados.The name of the stub class is the derived from the name of the interface, with "Fakes.Stub" as a prefix, and the parameter type names appended.

    El código auxiliar también se genera para captadores y establecedores de propiedades, para los eventos y para métodos genéricos.Stubs are also generated for the getters and setters of properties, for events, and for generic methods. Para obtener más información, vea Usar stubs para aislar las partes de la aplicación entre sí para las pruebas unitarias.For more information, see Use stubs to isolate parts of your application from each other for unit testing.

Introducción a las correcciones de compatibilidad (shim)Get started with shims

(Para obtener una descripción más detallada, vea Usar correcciones de compatibilidad (shim) para aislar la aplicación de otros ensamblados para las pruebas unitarias).(For a more detailed description, see Use shims to isolate your application from other assemblies for unit testing.)

Supongamos que el componente contiene las llamadas a DateTime.Now:Suppose your component contains calls to DateTime.Now:

// Code under test:
    public int GetTheCurrentYear()
    {
       return DateTime.Now.Year;
    }

Durante las pruebas, desea aplicar una corrección de compatibilidad (shim) a la propiedad Now porque la versión real devuelve de forma inapropiada un valor diferente en cada llamada.During testing, you would like to shim the Now property, because the real version inconveniently returns a different value at every call.

Para usar correcciones de compatibilidad (shims) no tiene que modificar el código de aplicación o escribirlo de una manera determinada.To use shims, you don't have to modify the application code or write it a particular way.

  1. Agregar un ensamblado de FakesAdd Fakes Assembly

    En el Explorador de soluciones, abra las referencias del proyecto de prueba unitaria y seleccione la referencia al ensamblado que contiene el método que quiera imitar.In Solution Explorer, open your unit test project's references and select the reference to the assembly that contains the method you want to fake. En este ejemplo, la clase DateTime está en System.dll.In this example, the DateTime class is in System.dll. Para ver las referencias en un proyecto de Visual Basic, seleccione Mostrar todos los archivos.To see the references in a Visual Basic project, choose Show All Files.

    Seleccione Agregar ensamblado de Fakes.Choose Add Fakes Assembly.

  2. Insertar una corrección de compatibilidad (shim) en ShimsContextInsert a shim in a ShimsContext

    [TestClass]
    public class TestClass1
    {
            [TestMethod]
            public void TestCurrentYear()
            {
                int fixedYear = 2000;
    
                // Shims can be used only in a ShimsContext:
                using (ShimsContext.Create())
                {
                  // Arrange:
                    // Shim DateTime.Now to return a fixed date:
                    System.Fakes.ShimDateTime.NowGet =
                    () =>
                    { return new DateTime(fixedYear, 1, 1); };
    
                    // Instantiate the component under test:
                    var componentUnderTest = new MyComponent();
    
                  // Act:
                    int year = componentUnderTest.GetTheCurrentYear();
    
                  // Assert:
                    // This will always be true if the component is working:
                    Assert.AreEqual(fixedYear, year);
                }
            }
    }
    
    <TestClass()> _
    Public Class TestClass1
        <TestMethod()> _
        Public Sub TestCurrentYear()
            Using s = Microsoft.QualityTools.Testing.Fakes.ShimsContext.Create()
                Dim fixedYear As Integer = 2000
                ' Arrange:
                ' Detour DateTime.Now to return a fixed date:
                System.Fakes.ShimDateTime.NowGet = _
                    Function() As DateTime
                        Return New DateTime(fixedYear, 1, 1)
                    End Function
    
                ' Instantiate the component under test:
                Dim componentUnderTest = New MyComponent()
                ' Act:
                Dim year As Integer = componentUnderTest.GetTheCurrentYear
                ' Assert:
                ' This will always be true if the component is working:
                Assert.AreEqual(fixedYear, year)
            End Using
        End Sub
    End Class
    

    Los nombres de clase Shim se componen anteponiendo Fakes.Shim al nombre de tipo original.Shim class names are made up by prefixing Fakes.Shim to the original type name. Los nombres de parámetro se anexan al nombre del método.Parameter names are appended to the method name. (No es necesario agregar referencias de ensamblado a System.Fakes).(You don't have to add any assembly reference to System.Fakes.)

En el ejemplo anterior se utiliza una corrección de compatibilidad (shim) para un método estático.The previous example uses a shim for a static method. Para utilizar una corrección de compatibilidad (shim) para un método de instancia, escriba AllInstances entre el nombre del tipo y el nombre del método:To use a shim for an instance method, write AllInstances between the type name and the method name:

System.IO.Fakes.ShimFile.AllInstances.ReadToEnd = ...

(No hay ningún ensamblado "System.IO.Fakes" al que hacer referencia.(There is no 'System.IO.Fakes' assembly to reference. El espacio de nombres lo genera el proceso de creación de correcciones de compatibilidad (shim),The namespace is generated by the shim creation process. pero puede usar "using" o "Import" de la manera habitual).But you can use 'using' or 'Import' in the usual way.)

También puede crear correcciones de compatibilidad (shims) para instancias concretas, para constructores y para propiedades.You can also create shims for specific instances, for constructors, and for properties. Para obtener más información, vea Usar correcciones de compatibilidad (shim) para aislar la aplicación de otros ensamblados para las pruebas unitarias.For more information, see Use shims to isolate your application from other assemblies for unit testing.

En esta secciónIn this section

Usar código auxiliar para aislar partes de la aplicación entre sí para las pruebas unitariasUse stubs to isolate parts of your application from each other for unit testing

Usar correcciones de compatibilidad (shim) para aislar la aplicación de otros ensamblados para las pruebas unitariasUse shims to isolate your application from other assemblies for unit testing

Generación de código, compilación y convenciones de nomenclatura en Microsoft FakesCode generation, compilation, and naming conventions in Microsoft Fakes