Aracılığıyla paylaş


Birim testi için uygulamanızın parçalarını birbirinden yalıtmak üzere saplamalar kullanma

Saplama türleri Microsoft Fakes framework çağırdığı diğer bileşenlerden test ettiğiniz bir bileşeni kolayca ayırmanıza olanak sağlayan iki teknoloji biridir. Bir saplama kodu başka bir bileşen sınaması sırasında gerçekleşir küçük bir parçasıdır. Bir saplama kullanmanın faydası test yazma kolaylaştırma tutarlı sonuçlar döndürmesidir. Ve diğer bileşenleri henüz çalışmıyor olsa bile, testleri çalıştırabilirsiniz.

Bir genel bakış ve Hızlı Başlat Kılavuzu Fakes için bkz: Microsoft Fakes ile Test Edilen Kodu Yalıtma.

Yer tutucular kullanmak için uygulamanın diğer bölümlerine başvurmak için sınıfların değil, yalnızca arabirimleri kullanır böylece bileşeninizin yazmak zorunda değilsiniz. Bu iyi tasarım uygulama çünkü bir bölümünde başka bir değişiklik gerektiren olası değişiklikleri yapar. Test etmek için gerçek bir bileşen için bir saplama koymak sağlar.

Diyagramda, StockAnalyzer sınamak istediğiniz bir bileşendir. Normal olarak, başka bir bileşen, RealStockFeed da kullanır. Ancak StockAnalyzer test etmek zorlaşır farklı sonuçlar RealStockFeed yöntemleri olarak adlandırılan her zaman döndürür. Sınama sırasında biz StubStockFeed bir farklı sınıfı değiştirin.

Gerçek ve saplama sınıf bir arabirim için uygun.

Kodunuzu bu yolla mümkün üzerinde yer tutucular dayandığından, genellikle yer tutucular başka bir uygulamanın bir parçası yalıtmak için kullanırsınız. Gelen, System.dll gibi kendi denetimi altında olan diğer derlemeler yalıtmak için dolgu verileri normal olarak kullanırsınız. Bkz: Birim testi için uygulamanızı diğer derlemelerden yalıtmak üzere dolgular kullanma

Gereksinimler

  • Visual Studio Ultimate

Bu konuda

Yer tutucular nasıl kullanılır?

Hh549174.collapse_all(tr-tr,VS.110).gifTasarım için bağımlılık ekleme

Yer tutucular kullanmak için uygulamanızın farklı bileşenler birbirine bağımlıdır, ancak arabirim tanımları yalnızca bağımlı değildir, böylece tasarlanmış vardır. Derleme zamanında bağlanmış yerine çalışma zamanında bileşenleri bağlıdır. Bu deseni değişiklikleri yaymak değil bileşen sınırları boyunca açabileceğinden güçlü ve kolay güncelleştirme yazılımı olmanıza yardımcı olur. Yer tutucular kullanmasanız bile, öneririz. Yeni kod yazıyorsanız, takip etmek kolay bağımlılık ekleme desen. Varolan yazılımı için testler yazıyorsanız, onu yeniden gerekebilir. Pratik olacaktır, dolgu verileri kullanmayı da deneyebilirsiniz.

Bu tartışma seçimini artıran bir örnek, bir diyagramdaki ile başlayalım. StockAnalyzer okur sınıf fiyatları paylaşmak ve bazı ilginç sonuçlar üretir. Sınamak istediğiniz bazı genel yöntemler var. Örneği basit tutmak için yalnızca bu yöntemler, belirli bir paylaşımın geçerli fiyat raporları çok basit bir tek tek bakalım. Birim testi o yöntemin yazmak istiyoruz. Testin ilk taslak aşağıdadır:

        [TestMethod]
        public void TestMethod1()
        {
            // Arrange:
            var analyzer = new StockAnalyzer();
            // Act:
            var result = analyzer.GetContosoPrice();
            // Assert:
            Assert.AreEqual(123, result); // Why 123?
        }
    <TestMethod()> Public Sub TestMethod1()
        ' Arrange:
        Dim analyzer = New StockAnalyzer()
        ' Act:
        Dim result = analyzer.GetContosoPrice()
        ' Assert:
        Assert.AreEqual(123, result) ' Why 123?
    End Sub

Bu test ile ilgili bir sorun hemen belirgin: paylaşım fiyatları farklılık gösterir ve bu nedenle onaylama işlemi genellikle başarısız olur.

StockAnalyzer tarafından kullanılan StockFeed bileşen hala geliştirilmekte olan başka bir sorun olabilir. İlk taslak test yönteminin kodu şöyledir:

        public int GetContosoPrice()
        {
            var stockFeed = new StockFeed(); // NOT RECOMMENDED
            return stockFeed.GetSharePrice("COOO");
        }
    Public Function GetContosoPrice()
        Dim stockFeed = New StockFeed() ' NOT RECOMMENDED
        Return stockFeed.GetSharePrice("COOO")
    End Function

Bunu anlamına gelir gibi bu yöntem derleme veya StockFeed sınıfındaki iş henüz tam olmadığı için bir özel durum fırlatabilir.

Arabirim ekleme bu sorunların her ikisini de giderir.

Arabirim ekleme aşağıdaki kural uygulanır:

  • Herhangi bir bileşenin uygulama kodu asla açıkça bir sınıfta bir bildirimi ya da başka bir bileşen için başvurmalıdır bir new ifadesi. Bunun yerine, değişkenler ve parametreleri ile arabirimlerinin bildirilmelidir. Bileşen örnekleri yalnızca bileşenin konteyner tarafından oluşturulmalıdır.

    "Bileşen" tarafından bu durumda biz bir sınıf veya sınıfların geliştirmek ve güncelleştirmek birlikte bir grup anlamına. Genellikle, bir Visual Studio proje kodunda bileşenidir. Aynı zamanda güncelleştirilmediğinden içinde bir bileşen sınıfları'nı mantığından ayrıştırmak daha az önemlidir.

    Ayrıca bileşenlerinizi System.dll gibi göreceli olarak tutarlı bir platform sınıfları'nı mantığından ayrıştırmak çok önemli değil. Bu sınıfların yazma kodunuzun karmaşıklığa.

StockAnalyzer kod bu nedenle, StockFeed benzer bir arabirim kullanarak ayrışımından tarafından geliştirilebilir:

    public interface IStockFeed
    {
        int GetSharePrice(string company);
    }

    public class StockAnalyzer
    {
        private IStockFeed stockFeed;
        public Analyzer(IStockFeed feed)
        {
            stockFeed = feed;
        }
        public int GetContosoPrice()
        {
            return stockFeed.GetSharePrice("COOO");
        }
    }
Public Interface IStockFeed
    Function GetSharePrice(company As String) As Integer
End Interface

Public Class StockAnalyzer
    ' StockAnalyzer can be connected to any IStockFeed:
    Private stockFeed As IStockFeed
    Public Sub New(feed As IStockFeed)
        stockFeed = feed
    End Sub  
    Public Function GetContosoPrice()
        Return stockFeed.GetSharePrice("COOO")
    End Function
End Class

Bu örnekte, yeniden oluşturulur, StockAnalyzer bir IStockFeed uygulaması geçirilir. Tamamlanan uygulamasında bağlantı başlatma kodu gerçekleştirmelisiniz:

analyzer = new StockAnalyzer(new StockFeed())

Bu bağlantıyı gerçekleştirme daha esnek bir yol vardır. Örneğin, StockAnalyzer, IStockFeed farklı koşullarda farklı uygulamaları oluşturabileceğiniz factory nesnesi kabul edemedi.

Hh549174.collapse_all(tr-tr,VS.110).gifYer tutucular oluştur

Bunu kullanan başka bir bileşenden test etmek istediğiniz sınıfı decoupled. Uygulama daha yapma yanı sıra güçlü ve esnek, bağlantıyı kesmeye bileşen arayüzlerinin test amaçları için uygulamalarına saplama testteki bağlanmanızı sağlar.

Yalnızca yer tutucular sınıfları olarak her zamanki yolla yazabilirsiniz. Ancak Microsoft Fakes, her test için en uygun saplama oluşturmak için daha dinamik bir yol sağlar.

Yer tutucular kullanmak için önce arabirim tanımları saplama türleri oluşturmanız gerekir.

Fakes derleme ekleme

  1. Birim test projenizin Solution Explorer'da genişletin başvuruları.

    • Visual Basic'te çalışırken, seçmelisiniz Tüm dosyaları göster başvurular listesini görmek için Çözüm Gezgini araç çubuğunda.
  2. Yer tutucular oluşturmak istediğiniz arabirim tanımlarını içeren bütünleştirilmiş kodunu seçin.

  3. Kısayol menüsünde Fakes derleme Ekle.

Hh549174.collapse_all(tr-tr,VS.110).gifYer tutucular ile test yazma

[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

Özel Sihirli burada sınıf parçasıdır StubIStockFeed. Başvurulan derlemedeki ortak her tür Microsoft Fakes mekanizması bir saplama sınıf oluşturur. Saplama sınıf adı ile türetilen arabirimin adı olan "Fakes.Stub" olarak bir önek ve parametre türü adları eklenmiş.

Yer tutucular da alıcılar ve ayarlayıcılar özellikleri, olayları ve genel yöntemler için oluşturulur.

Hh549174.collapse_all(tr-tr,VS.110).gifParametre değerlerini doğrulama

Bileşenin başka bir bileşenden bir çağrı yaptığında, onu doğru değerleri geçiren doğrulayabilirsiniz. Bir onaylama işlemi yerel yordamında yerleştirebilirsiniz veya değeri saklayın ve testin ana gövdesini de doğrulayın. Örne?in:

[TestClass]
class TestMyComponent
{
       
    [TestMethod]
    public void TestVariableContosoPrice()
    {
     // Arrange:
        int priceToReturn;
        string companyCodeUsed;
        var componentUnderTest = new StockAnalyzer(new StubIStockFeed()
            {
               GetSharePriceString = (company) => 
                  { 
                     // Store the parameter value:
                     companyCodeUsed = company;
                     // Return the value prescribed by this test:
                     return priceToReturn;
                  };
            };
        // Set the value that will be returned by the stub:
        priceToReturn = 345;

     // Act:
        int actualResult = componentUnderTest.GetContosoPrice(priceToReturn);

     // Assert:
        // Verify the correct result in the usual way:
        Assert.AreEqual(priceToReturn, actualResult);

        // Verify that the component made the correct call:
        Assert.AreEqual("COOO", companyCodeUsed);
    }
...}
<TestClass()> _
Class TestMyComponent
    <TestMethod()> _
    Public Sub TestVariableContosoPrice()
        ' Arrange:
        Dim priceToReturn As Integer
        Dim companyCodeUsed As String = ""
        Dim stockFeed As New StockAnalysis.Fakes.StubIStockFeed()
        With stockFeed
            ' Implement the interface's method:
            .GetSharePriceString = _
                Function(company)
                    ' Store the parameter value:
                    companyCodeUsed = company
                    ' Return a fixed result:
                    Return priceToReturn
                End Function
        End With
        ' Create an object to test:
        Dim componentUnderTest As New StockAnalyzer(stockFeed)
        ' Set the value that will be returned by the stub:
        priceToReturn = 345

        ' Act:
        Dim actualResult As Integer = componentUnderTest.GetContosoPrice()

        ' Assert:
        ' Verify the correct result in the usual way:
        Assert.AreEqual(priceToReturn, actualResult)
        ' Verify that the component made the correct call:
        Assert.AreEqual("COOO", companyCodeUsed)
    End Sub
...
End Class

Değişik tür üyeleri için yer tutucular

Hh549174.collapse_all(tr-tr,VS.110).gifYöntemler

Örnekte açıklandığı gibi yöntemler saplama sınıfının bir örneği için bir temsilci ekleyerek stubbed. Saplama türünün adı yöntemi ve parametreleri adlarından türetilir. Örneğin, aşağıda verilen IMyInterface arabirimi ve yöntem MyMethod:

// application under test
interface IMyInterface 
{
    int MyMethod(string value);
}

Bir MyMethod 'a saplama ekleyebiliriz o her zaman 1 döndürür:

// unit test code
  var stub = new StubIMyInterface ();
  stub.MyMethodString = (value) => 1;

Fakes işlevi için bir saplama belirtmezseniz, dönüş türü, varsayılan değer döndüren bir işlev oluşturur. Sayılar için varsayılan değer 0'dır ve sınıf türleri için konulan null (C#) veya Nothing (Visual Basic).

Hh549174.collapse_all(tr-tr,VS.110).gifÖzellikler

Özellik alıcılar ve ayarlayıcılar, ayrı temsilciler olarak sunulur ve ayrı ayrı saplanmış olabilirler. Örneğin, IMyInterface için Value özelliğini göz önüne alın:

// code under test
interface IMyInterface 
{
    int Value { get; set; }
}

Otomatik özellik benzetimi için Value alıcı ve ayarlayıcısına temsilcileri ekleyin:

// unit test code
int i = 5;
var stub = new StubIMyInterface();
stub.ValueGet = () => i;
stub.ValueSet = (value) => i = value;

Ayarlayıcı veya özellik alıcısı için saplama yöntemleri belirtmezseniz, saplama özelliği gibi basit bir değişkene çalışır böylece Fakes, değerleri depolayan bir saplama oluşturacaktır.

Hh549174.collapse_all(tr-tr,VS.110).gifOlaylar

Olaylar, temsilci alanları olarak sunulur. Sonuç olarak herhangi bir saplama olayı, olay yedekleme alanını çağırarak basitçe yükseltilebilir. Saplama için yandaki arayüzü göz önünde bulunduralım:

// code under test
interface IWithEvents 
{
    event EventHandler Changed;
}

Bir Changed olayını yükseltmek için, sadece yedekleme temsilcisini çağırırız:

// unit test code
  var withEvents = new StubIWithEvents();
  // raising Changed
  withEvents.ChangedEvent(withEvents, EventArgs.Empty);

Hh549174.collapse_all(tr-tr,VS.110).gifGenel yöntemler

Yöntemin istenen her örneklemesi için temsilci sağlayarak, genel yöntemleri saplamak mümkündür. Örneğin, aşağıda verilen arayüz bir genel yöntem içerir:

// code under test
interface IGenericMethod 
{
    T GetValue<T>();
}

dosyaya yerleştirir bir test yazabilirsiniz GetValue<int> örnekleme:

// unit test code
[TestMethod]
public void TestGetValue() 
{
    var stub = new StubIGenericMethod();
    stub.GetValueOf1<int>(() => 5);

    IGenericMethod target = stub;
    Assert.AreEqual(5, target.GetValue<int>());
}

Kod çağırmak için GetValue<T> diğer herhangi bir örnekleme ile saplama basitçe davranışı çağıracak.

Hh549174.collapse_all(tr-tr,VS.110).gifSanal sınıfların yer tutucular

Önceki örneklerde, yer tutucular arabirimlerden üretilmedi. Sanal veya Özet üyeler bir sınıftan yer tutucular da oluşturabilir. Örne?in:

// Base class in application under test
    public abstract class MyClass
    {
        public abstract void DoAbstract(string x);
        public virtual int DoVirtual(int n)
        { return n + 42; }
        public int DoConcrete()
        { return 1; }
    }

Bu sınıftan oluşturulmuş yerel yordamında, DoAbstract() ve DoVirtual(), ancak değil DoConcrete() temsilci yöntemleri ayarlayabilirsiniz.

// unit test
  var stub = new Fakes.MyClass();
  stub.DoAbstractString = (x) => { Assert.IsTrue(x>0); };
  stub.DoVirtualInt32 = (n) => 10 ;
  

Sanal bir yöntem için temsilci belirtmezseniz, Fakes ya da varsayılan davranışı sağlayabilir veya temel sınıf yöntemi çağırabilirsiniz. Olarak adlandırılan temel yöntemi için set CallBase özelliği:

// unit test code
var stub = new Fakes.MyClass();
stub.CallBase = false;
// No delegate set – default delegate:
Assert.AreEqual(0, stub.DoVirtual(1));

stub.CallBase = true;
//No delegate set - calls the base:
Assert.AreEqual(43,stub.DoVirtual(1));

Hata ayıklama saplamaları

Saplama türleri, yumuşak bir hata ayıklama deneyimini sağlamak üzere tasarlanmıştır. Varsayılan olarak, hata ayıklayıcı herhangi bir oluşturulan kod üzerinde adım adım ilerler, bu nedenle saplamaya eklenmiş olan özel üye uygulamalarının içine doğrudan atlar.

Saplama sınırlamaları

  1. İşaretçilerle birlikte yöntem imzaları desteklenmez.

  2. Saplama sınıfları veya statik yöntemleri saplanmamalı; çünkü saplama türü sanal yöntem gönderimine dayanır. Bu gibi durumlarda Birim testi için uygulamanızı diğer derlemelerden yalıtmak üzere dolgular kullanma içinde açıklandığı gibi dolgu türleri kullanın.

Saplamaların varsayılan davranışını değiştirme

Her üretilen saplama türü, IStubBehavior arabiriminin bir örneğini taşır ( IStub.InstanceBehavior özelliği aracılığıyla). Hiç eklenmemiş özel temsilci ile üye istemci çağrıları olarak adlandırılır. Eğer davranış ayarlanmamışsa; StubsBehaviors.Current özelliği tarafından döndürülen örneği kullanabilirsiniz. Varsayılan olarak bu özellik, NotImplementedException özel durumunu atan bir davranış döndürür.

Davranış, herhangi bir saplamadaki InstanceBehavior özelliğini ayarlayarak herhangi bir zamanda değişebilir. Örneğin aşağıdaki kod parçacığı, hiçbir şey yapmaz olarak veya dönüş türünün varsayılan değerini döndürür olarak davranışı değiştirir: default(T):

// unit test code
var stub = new StubIFileSystem();
// return default(T) or do nothing
stub.InstanceBehavior = StubsBehaviors.DefaultValue;

Davranış, StubsBehaviors.Current özelliğini ayarlayarak davranışı ayarlanmamış tüm saplama nesneleri için genel olarak değiştirebilir:

// unit test code
//change default behavior for all stub instances
//where the behavior has not been set
StubBehaviors.Current = 
    BehavedBehaviors.DefaultValue;

Dış kaynaklar

Hh549174.collapse_all(tr-tr,VS.110).gifKılavuz

Visual Studio 2012 – bölüm 2 ile sürekli teslimat için sınama: birim testi: iç sınama

Ayrıca bkz.

Kavramlar

Microsoft Fakes ile Test Edilen Kodu Yalıtma