2015-06-09 20 views
10

Akka.NET oyuncularımı test etmeye çalışıyorum, ancak TestKit ile bazı problemler yaşıyor ve nasıl çalıştığını anlıyoruz. Orada Akka.NET içinde birim test için hiçbir resmi belgeler henüz yanaAkka.NET'de TestKit nasıl kullanılır

, ben örnek kodu için Akka.NET repo araştırmalarımız oldu, ancak örnekler benim için orada çalışmıyor kullanılır.

Referans için kullandığım testler, uygulamanızda test etmeye çalıştığım senaryoya yakın oldukları için ReceiveActorTests.cs ve ReceiveActorTests_Become.cs'dur.

İşte bazı kukla kod: Bu aktör Ben doğru Tebrik Aldı ve Veda mesajları olduğunu test etmek istiyorum

public class Greeter : ReceiveActor 
{ 
    public Greeter() 
    { 
     NotGreeted(); 
    } 

    private void NotGreeted() 
    { 
     Receive<Greeting>(msg => Handle(msg)); 
    } 

    private void Greeted() 
    { 
     Receive<Farewell>(msg => Handle(msg)); 
    } 

    private void Handle(Greeting msg) 
    { 
     if (msg.Message == "hello") 
     { 
      Become(Greeted); 
     } 
    } 

    private void Handle(Farewell msg) 
    { 
     if (msg.Message == "bye bye") 
     { 
      Become(NotGreeted); 
     } 
    } 
} 

Verilen

ve doğru ol-devletleri girer. Bir aktör başlatmasını bu yaklaşım deneyin ve ne zaman ReceiveActorTests_Become.cs testler bakıldığında, bir aktör

var system = ActorSystem.Create("test"); 
var actor = system.ActorOf<BecomeActor>("become"); 

tarafından oluşturulur ve bir mesaj Ancak

actor.Tell(message, TestActor); 
ExpectMsg(message); 

tarafından gönderilen ve ileri sürülür diğerleri dayalı

: Bu benim sınavım

Xunit.Sdk.TrueExceptionFailed: Timeout 00:00:03 while waiting for a message of type ConsoleApplication1.Greeting 
Expected: True 
Actual: False 

: test kiti yöntemleri (aşağıya bakınız), ben diğer müzikleri testi başarısız hatası almaya devam

public class XUnit_GreeterTests : TestKit 
{ 
    [Fact] 
    public void BecomesGreeted() 
    { 
     //var system = ActorSystem.Create("test-system"); // Timeout error 
     //var actor = system.ActorOf<Greeter>("greeter"); // Timeout error 
     //var actor = ActorOfAsTestActorRef<Greeter>("greeter"); // Timeout error 
     //var actor = ActorOf(() => new Greeter(), "greeter"); // Timeout error 
     //var actor = Sys.ActorOf<Greeter>("greeter"); // Timeout error 
     //var actor = Sys.ActorOf(Props.Create<Greeter>(), "greeter"); // Timeout error 
     var actor = CreateTestActor("greeter"); // Works, but doesn't test my Greeter actor, but rather creates a generic TestActor (as I understand it) 

     var message = new Greeting("hello"); 

     actor.Tell(message, TestActor); 

     ExpectMsg(message); 
    } 
} 

Ayrıca, ExpectMsg satırını aktörün üstünden hareket ettirmeyi de denedim.Tell satırı (bir şey üzerinde harekete geçmeden önce bir şey beklemeniz ve sonra beklentiyi doğrulamanız daha mantıklı olduğundan), ancak bu aynı zamanda Zaman Aşımı hatasıyla sonuçlanır. .

Hem NUnit hem de XUnit TestKit'leri ile denedim.

Muhtemelen gözden kaçan gerçekten temel bir şey var.

+0

Bu derin tanıtımı TestKit'e ve nasıl kullanılacağı ile ilgilenebilirsiniz. Önümüzdeki hafta canlı yayınlanması gereken uzun soluklu belgelerin habercisi >> https://petabridge.com/blog/akka-testkit-introduction/ (açıklama: Yazdım) – AndrewS

cevap

14

test kiti sizin aktörler bütün aktör sistemi bağlamında beklendiği gibi çalışıp çalışmadığını doğrulamak için daha fazla davranışsal testleri için kullanılır.Bu daha çok kara kutu testi gibidir - doğrudan bir aktörün içlerine ulaşamazsınız. Bunun yerine, no'lu A sinyali ve aktör davranışı B gibi davranışlara odaklanmak daha iyidir. Bu, C iletisini başka bir oyuncuya D göndermelidir.

Örnek sorununuzda, Greeter aktörü, sessizdir - bazı girişler alınabilirken, sonuçta hiçbir şey yapmaz. Bütün sistemin perspektifinden ölebilir ve kimse umursamaz.

diğer örneği kullanarak - Verilen aşağıdaki aktör: Gördüğünüz gibi

public class GreeterSpec : TestKit 
{ 
    private IActorRef greeter; 

    public GreeterSpec() : base() 
    { 
     greeter = Sys.ActorOf<Greeter>("TestGreeter"); 
    } 

    [Fact] 
    public void Greeter_should_GreetBack_when_Greeted() 
    { 
     // set test actor as message sender 
     greeter.Tell(new Greet("John Snow"), TestActor); 
     // ExpectMsg tracks messages received by TestActors 
     ExpectMsg<GreetBack>(msg => msg.Who == "TestGreeter"); 
    } 

    [Fact] 
    public void Greeter_should_broadcast_incoming_greetings() 
    { 
     // create test probe and subscribe it to the event bus 
     var subscriber = CreateTestProbe(); 
     Sys.EventStream.Subscribe(subscriber.Ref, typeof (string)); 

     greeter.Tell(new Greet("John Snow"), TestActor); 

     // check if subscriber received a message 
     subscriber.ExpectMsg<string>("John Snow sends greetings"); 
    } 
} 

, burada aktör iç durumunu kontrol etmiyoruz:

public class Greeter : ReceiveActor 
{ 
    public Greeter() 
    { 
     Receive<Greet>(greet => 
     { 
      // when message arrives, we publish it on the event stream 
      // and send response back to sender 
      Context.System.EventStream.Publish(greet.Who + " sends greetings"); 
      Sender.Tell(new GreetBack(Self.Path.Name)); 
     }); 
    } 
} 

Bunu örnek bir deney spec yaratalım . Bunun yerine, gönderdiğim sinyallere nasıl tepki verdiğini gözlemliyorum ve beklenen bir sonuç olup olmadığını doğrularım.

+1

Bu çok mantıklı, teşekkürler. Dolayısıyla, bir aktörün belirli bir Be-state durumunda olduğunu test etmenin tek yolu, bu durumda belirli mesaj tiplerini yayıp yaymadığını görmektir. – ardal

+2

Temel olarak evet. * Paylaşarak iletişim kurmayın, iletişim yoluyla paylaşın * sloganı doğrudan aktörün durumuna ulaşmazsınız (çünkü belirli bir aktör benim reenkarne sonuncum başarısızlık veya farklı makineye yerleştirilebilir ve her şey eşzamanlı değildir). Davranışını gelen sinyallerde tepki vermesiyle doğrulayabilirsiniz. – Horusiath

4

Sen ve oluşturmamalıdır yok senin ActorSystem kendi herhangi Akka.TestKit testinin bir parçası olarak. Sys özelliğini dahili testlerinizde kullanabilirsiniz ve TestKit tarafından kullanılan aynı ActorSystem erişimini elde edersiniz.

Yani böyle bir şey yapmalıdır:

var actor = Sys.ActorOf<BecomeActor>("become"); 

nedeni bu neden önemli olduğu: onları birbirine mesaj göndermek için sahip aynı ActorSystem içinde TestActor ve sizin BecomeActor gerekli olan Akka.Remote kullanmıyorsanız. Aksi halde TestActor hiçbir iletiyi alamıyor ve ExpectMsg çağrılarınız zaman aşımına uğrayacaktır.

DÜZENLEME: tüm test aktör sistemi şimdi birim testler arasında yırtılmış.

DÜZENLEME 2: detailed guide we wrote to the Akka.NET TestKit for a longer explanation bakınız.

+0

Çok açıklar, teşekkürler. Başka bir şey, TestKit'i kullanarak bir aktörün yaratılışının bazı yolları arasındaki fark nedir? Gibi: var aktör = ActorOfAsTestActorRef ("karşılama"); var aktör = Sys.ActorOf ("karşılama"); var actor = Sys.ActorOf (Props.Create (), "karşılama") var aktör = ActorOf (() => yeni Greeter(), "karşılama"); Bunların hepsi aynı oyuncuyla sonuçlanacak mı? Nasıl farklılar? – ardal

+1

Tüm Sys.ActorOf yöntemleri, eşdeğerdir. 'ActorOfAsTestActorRef', 'TestActor'ın bir çocuğu olarak aktörünüzü oluşturacak – Aaronontheweb

+0

, hala testlerle alakalı @Aaronontheweb arasında hala canlı olan aktörler hakkındaki yorumdur? Akka.Net ve TestKit'e yeni giriş yaptım ve buradaki en son belgeler https://petabridge.com/blog/how-to-unit-test-akkadotnet-actors-akka-testkit/ tamamen kaldırıldığını ve Her test için şimdi yeniden oluşturuldu – nrjohnstone