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

Nota

  • 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:In Solution Explorer,

      • Para un proyecto de .NET Framework anterior (que no sea de estilo SDK), expanda el nodo Referencias del proyecto de pruebas unitarias.For an older .NET Framework Project (non-SDK style), expand your unit test project's References node.
      • Para un proyecto de estilo SDK que tenga como destino .NET Framework, .NET Core o .NET 5.0, expanda el nodo Dependencias para buscar el ensamblado que quiere imitar en Ensamblados, Proyectos o Paquetes.For an SDK-style project targeting .NET Framework, .NET Core, or .NET 5.0, expand the Dependencies node to find the assembly you would like to fake under Assemblies, Projects, or Packages.
      • Si está trabajando en Visual Basic, seleccione Mostrar todos los archivos en la barra de herramientas del Explorador de soluciones para ver el nodo Referencias.If you're working in Visual Basic, select Show All Files in the Solution Explorer toolbar to see the References node.
    2. Seleccione el ensamblado que contiene las definiciones de clases para las que desea crear las correcciones de compatibilidad (shim).Select the assembly that contains the class definitions for which you want to create shims. Por ejemplo, si quiere realizar una corrección de compatibilidad para DateTime, seleccione System.dll.For example, if you want to shim DateTime, select System.dll.

    3. En el menú contextual, seleccione Agregar ensamblado de Fakes.On the shortcut menu, choose Add Fakes Assembly.

  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 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.

Uso de Microsoft Fakes en la canalización de CIUsing Microsoft Fakes in the CI

Generación de ensamblados de Microsoft FakesMicrosoft Fakes Assembly Generation

Dado que Microsoft Fakes requiere Visual Studio Enterprise, para generar ensamblados de Fakes, hay que compilar el proyecto con una tarea de compilación de Visual Studio.Since Microsoft Fakes requires Visual Studio Enterprise, the generation of Fakes Assemblies requires that you build your project using Visual Studio Build Task.

Nota

También se pueden comprobar los ensamblados de Fakes en la canalización de CI y usar una tarea de MSBuild.An alternative to this is to check your Fakes Assemblies into the CI and use the MSBuild Task. Al hacerlo, debe asegurarse de que tiene una referencia de ensamblado al ensamblado de Fakes generado en el proyecto de prueba, que es similar al siguiente fragmento de código:When you do this, you need to ensure that you have an assembly reference to the generated Fakes assembly in your test project, similar to the following code snippet :

<Project Sdk="Microsoft.NET.Sdk">
    <ItemGroup>
        <Reference Include="FakesAssemblies\System.Fakes.dll">
    </ItemGroup>
</Project>

Esta referencia debe agregarse de forma manual y específica en proyectos de estilo SDK (.NET Core, .NET 5.0 y .NET Framework), ya que ahora las referencias de ensamblado se tienen que agregar implícitamente al proyecto de prueba.This reference is required to be added in manually specifically SDK-style projects (.NET Core, .NET 5.0, and .NET Framework) because we have moved to implicitly adding assembly references to your test project. Si sigue este método, debe asegurarse de que el ensamblado de Fakes se actualice cuando cambia el ensamblado primario.If you follow this method, you need to ensure that the fakes assembly is updated when the parent assembly changes.

Ejecución de pruebas de Microsoft FakesRunning Microsoft Fakes tests

Siempre que los ensamblados de Microsoft Fakes estén presentes en el directorio configurado FakesAssemblies (el valor predeterminado es $(ProjectDir)FakesAssemblies), puede ejecutar las pruebas mediante la tarea VSTest.As long as Microsoft Fakes assemblies are present in the configured FakesAssemblies directory (The default being $(ProjectDir)FakesAssemblies), you can run tests using the vstest task.

Para realizar pruebas distribuidas con la tarea VSTest en proyectos de .NET Core y .NET 5.0 que usan Microsoft Fakes, se requiere Visual Studio 2019 Update 9 Preview 20201020-06 y versiones posteriores.Distributed testing with the vstest task .NET Core and .NET 5.0 projects using Microsoft Fakes requires Visual Studio 2019 Update 9 Preview 20201020-06 and higher.

Transición de los proyectos de prueba de .NET Framework que usan Microsoft Fakes a proyectos de .NET Framework, .NET Core o .NET 5.0 de estilo SDKTransitioning your .NET Framework test projects that use Microsoft Fakes to SDK-style .NET Framework, .NET Core, or .NET 5.0 projects

Solo necesitará realizar unos pocos cambios en el entorno de .NET Framework configurado para Microsoft Fakes para llevar a cabo la transición a .NET Core o .NET 5.0.You will need minimal changes in your .NET Framework set up for Microsoft Fakes to transition to .NET Core or .NET 5.0. Debe tener en cuenta los siguientes casos:The cases that you would have to consider are:

  • Si usa una plantilla de proyecto personalizada, debe asegurarse de que sea de estilo SDK y de que se compile para una plataforma de destino compatible.If you are using a custom project template, you need to ensure that it is SDK-style and builds for a compatible target framework.
  • Hay algunos tipos que ya se encuentran en diferentes ensamblados de .NET Framework y .NET Core/.NET 5.0 (por ejemplo, System.DateTime existe en System/mscorlib en .NET Framework, y en System.Runtime en .NET Core y .NET 5.0); en estos escenarios debe cambiar el ensamblado que se va a imitar.Certain types exist in different assemblies in .NET Framework and .NET Core/.NET 5.0 (for example, System.DateTime exists in System/mscorlib in .NET Framework, and in System.Runtime in .NET Core and .NET 5.0), and in these scenarios you need to change the assembly being faked.
  • Si tiene una referencia de ensamblado a un ensamblado de Fakes y al proyecto de prueba, es posible que vea una advertencia de compilación que indica que falta una referencia similar a la siguiente:If you have an assembly reference to a fakes assembly and the test project, you might see a build warning about a missing reference similar to:
    (ResolveAssemblyReferences target) ->
    warning MSB3245: Could not resolve this reference. Could not locate the assembly "AssemblyName.Fakes". Check to make sure the assembly exists on disk.
    If this reference is required by your code, you may get compilation errors.
    
    Esta advertencia se produce porque pueden omitirse los cambios necesarios realizados en la generación de ensamblados de Fakes.This warning is due to necessary changes made in Fakes generation can be ignored. Para evitarla, se puede quitar la referencia de ensamblado del archivo de proyecto, ya que ahora se agrega implícitamente durante la compilación.It can be avoided by removing the assembly reference from the project file, because we now implicitly add them during the build.

Compatibilidad de Microsoft FakesMicrosoft Fakes support

Microsoft Fakes en proyectos antiguos que tienen como destino .NET Framework (estilo que no sea de SDK).Microsoft Fakes in older projects targeting .NET Framework (non-SDK style).

  • La generación de ensamblados de Microsoft Fakes es compatible con Visual Studio Enterprise 2015 y versiones posteriores.Microsoft Fakes assembly generation is supported in Visual Studio Enterprise 2015 and higher.
  • Las pruebas de Microsoft Fakes se pueden ejecutar con todos los paquetes de NuGet Microsoft.TestPlatform disponibles.Microsoft Fakes tests can run with all available Microsoft.TestPlatform NuGet packages.
  • La cobertura de código es compatible con los proyectos de prueba que usan Microsoft Fakes en Visual Studio Enterprise 2015 y versiones posteriores.Code coverage is supported for test projects using Microsoft Fakes in Visual Studio Enterprise 2015 and higher.

Microsoft Fakes en proyectos de .NET Framework, .NET Core y .NET 5.0 de estilo SDKMicrosoft Fakes in SDK-style .NET Framework, .NET Core, and .NET 5.0 projects

  • La generación de ensamblados de Microsoft Fakes, en versión preliminar en Visual Studio Enterprise 2019 Update 6, ya está habilitada de forma predeterminada en Update 8.Microsoft Fakes assembly generation previewed in Visual Studio Enterprise 2019 Update 6 and is enabled by default in Update 8.
  • Las pruebas de Microsoft Fakes para los proyectos que tienen como destino .NET Framework pueden ejecutarse con todos los paquetes de NuGet Microsoft.TestPlatform disponibles.Microsoft Fakes tests for projects that target .NET Framework can run with all available Microsoft.TestPlatform NuGet packages.
  • Las pruebas de Microsoft Fakes para los proyectos que tienen como destino .NET Core y .NET 5.0 pueden ejecutarse con los paquetes NuGet Microsoft.TestPlatform con las versiones 16.9.0-preview-20210106-01 y posteriores.Microsoft Fakes tests for projects that target .NET Core and .NET 5.0 can run with Microsoft.TestPlatform NuGet packages with versions 16.9.0-preview-20210106-01 and higher.
  • La cobertura de código es compatible con los proyectos de prueba que tienen como destino .NET Framework y que usan Microsoft Fakes en Visual Studio Enterprise 2015 y versiones posteriores.Code coverage is supported for test projects targeting .NET Framework using Microsoft Fakes in Visual Studio Enterprise version 2015 and higher.
  • La compatibilidad con la cobertura de código en los proyectos de prueba que tienen como destino .NET Core y .NET 5.0 y que usan Microsoft Fakes está disponible en Visual Studio 2019 Update 9 y versiones posteriores.Code coverage support for test projects targeting .NET Core and .NET 5.0 using Microsoft Fakes is available in Visual Studio 2019 update 9 and higher.

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