1

Rhino Mocks AAA sözdizimini öğrenmeye çalışıyorum ve belirli bir yöntemin (herhangi bir argüman değeriyle) çağrıldığını sorun yaşıyorum. Test framework'üm olarak Machine.Specifications kullanıyorum.RhinoMocks kullanarak üç farklı türden genel bir yöntem nasıl kullanılır?

Bu özel yöntem geneldir ve üç farklı türde üç kez çağrıldığından emin olmak istiyorum.

repo.Save<T1>(anything), repo.Save<T2>(anything), and repo.Save<T3>(anything) 

Her tür için işlevi durdurdum. Ama ilginç bir sonuç alıyorum. (aşağıdaki)

[Subject("Test")] 
public class When_something_happens_with_constraint 
{ 
    static IRepository repo; 
    static TestController controller; 
    static ActionResult result; 

    Establish context =() => 
    { 
     repo = MockRepository.GenerateMock<IRepository>(); 
     controller = new TestController(repo); 
     repo.Stub(o => o.Save<Something>(Arg<Something>.Is.Anything)); 
     repo.Stub(o => o.Save<SomethingElse>(Arg<SomethingElse>.Is.Anything)); 
     repo.Stub(o => o.Save<AnotherOne>(Arg<AnotherOne>.Is.Anything)); 
    }; 

    //post data to a controller 
    Because of =() => { result = controller.SaveAction(new SomethingModel() { Name = "test", Description = "test" }); }; 

    //controller constructs its own something using the data posted, then saves it. I want to make sure three calls were made. 
    It Should_save_something =() => repo.AssertWasCalled(o => o.Save<Somethign>(Arg<Something>.Is.Anything)); 
    It Should_save_something_else =() => repo.AssertWasCalled(o => o.Save<SomethingElse>(Arg<SomethingElse>.Is.Anything)); 
    It Should_save_another_one =() => repo.AssertWasCalled(o => o.Save<AnotherOne>(Arg<AnotherOne>.Is.Anything)); 
} 

Sonuç iki istisna ve bir geçiştir.

ilk çağrı atar:

System.InvalidOperationException: Hiçbir beklentileri doğrulanacak kurulum vardı eylemde yöntem çağrısı sanal (C#) olmasını sağlamak/geçersiz kılınabilir (VB.Net) yöntemi çağrısı

ikincisi atar:

System.InvalidOperationException: Kullanım Arg SADECE sahte yöntem çağrı içinde kayıt sırasında. 1 argüman bekleniyor, 2 tane tanımlandı.

Üçüncüsü, bazı garip nedenlerden dolayı geçer.

Ayrıca, kurulumumda GenerateMock() ile Expect'i kullanmayı ve Stub ile GenerateStub() öğesini kullanmayı denedim. Her ikisi de aynı sonuçla sona erdi. Yanlış bir şey yapmalıyım.

kullanıyorum: MachineSpec 0.3.0.0 ve 3.6.0.0 RhinoMocks

Herhangi bir fikir?

----- İşte Lee'nin yardımıyla tam (çalışma versiyonu) var SABİT ----------

. Ekstra (linq olmayan) bir katman kullanıyorum. Benim asıl sorun benim testlerimden birinin çevrimdışı gerçek kodda yanlış lambda değişkenini tekrar kullanmasıydı. It Should_do_something =() => repo.AssertWasCalled (o =>repo .Save (veri)); // bad lambda

İşte referans için doğru test örneği.

using System; 
using System.Linq; 
using System.Collections.Generic; 
using Machine.Specifications; 
using Rhino.Mocks; 

namespace OnlineTesting.Specifications 
{ 
    public interface Repository 
    { 
     void Save<T>(T data); 
     IQueryable<T> All<T>(); 
    } 

    public interface Service 
    { 
     void SaveItem(Item data); 
     void SaveAnotherItem(AnotherItem data); 
     void SaveOtherItem(OtherItem data); 
     List<Item> GetItems(); 
     List<AnotherItem> GetAnotherItems(); 
     List<OtherItem> GetOtherItems(); 
    } 

    public class ConcreteService : Service 
    { 
     Repository repo; 
     public ConcreteService(Repository repo) 
     { 
      this.repo = repo; 
     } 
     public void SaveItem(Item data) 
     { 
      repo.Save(data); 
     } 
     public void SaveAnotherItem(AnotherItem data) 
     { 
      repo.Save(data); 
     } 
     public void SaveOtherItem(OtherItem data) 
     { 
      repo.Save(data); 
     } 

     public List<Item> GetItems() 
     { 
      return repo.All<Item>().ToList(); 
     } 
     public List<AnotherItem> GetAnotherItems() 
     { 
      return repo.All<AnotherItem>().ToList(); 
     } 
     public List<OtherItem> GetOtherItems() 
     { 
      return repo.All<OtherItem>().ToList(); 
     } 
    } 

    public class Item 
    { 
     public int Id { get; set; } 
    } 
    public class OtherItem 
    { 
    } 
    public class AnotherItem 
    { 
    } 


    public class When_something_else_happens 
    { 
     Establish context =() => 
     { 
      _repository = MockRepository.GenerateMock<Repository>(); 
      _service = new ConcreteService(_repository); 
      _controller = new TestController(_service); 

      _repository.Stub(o => o.Save<Item>(Arg<Item>.Is.Anything)).WhenCalled(
       new Action<MethodInvocation>((o) => 
       { 
        var data = o.Arguments.FirstOrDefault() as Item; 
        if (data != null && data.Id == 0) 
         data.Id++; 
       })); 
     }; 

     Because of =() => _controller.DoSomethingElse(); 

     It should_save_the_first_thing =() => 
      _repository.AssertWasCalled(repo => repo.Save(Arg<Item>.Is.Anything)); 

     It should_save_the_other_thing =() => 
      _repository.AssertWasCalled(repo => repo.Save(Arg<OtherItem>.Is.Anything)); 

     It should_save_the_last_thing =() => 
      _repository.AssertWasCalled(repo => repo.Save(Arg<AnotherItem>.Is.Anything)); 

     static Repository _repository; 
     static TestController _controller; 
     static Service _service; 
    } 

    public class TestController 
    { 
     readonly Service _service; 

     public TestController(Service service) 
     { 
      _service = service; 
     } 

     public void DoSomethingElse() 
     { 
      _service.SaveItem(new Item()); 
      _service.SaveOtherItem(new OtherItem()); 
      _service.SaveAnotherItem(new AnotherItem()); 
     } 
    } 
} 
+0

Ayrıca ... Denetleyici eylemi yeni bir nesne oluşturduğundan ve depoya geçirdiğinden, aramadan önce bağımsız değişkenleri ayarlayamıyorum. Bu yüzden Arg .Is.Anything kullanıyorum. Ben sadece belirli bir tür için repo.save çağrıldığından emin olmak istiyorum. – Nathan

cevap

0

Bunu bir deneyin.

[Subject("Test")] 
public class When_something_happens_with_constraint 
{ 
    static IRepository repo; 
    static TestController controller; 
    static ActionResult result; 

    Establish context =() => 
    { 
     repo = MockRepository.GenerateMock<IRepository>(); 
     controller = new TestController(repo); 
    }; 

    //post data to a controller 
    Because of =() => result = controller.SaveAction(new SomethingModel() { Name = "test", Description = "test" }); 

    //controller constructs its own something using the data posted, then saves it. I want to make sure three calls were made. 
    It Should_save_something =() => repo.AssertWasCalled(o => o.Save(Arg<Something>.Is.Anything)); 
    It Should_save_something_else =() => repo.AssertWasCalled(o => o.Save(Arg<SomethingElse>.Is.Anything)); 
    It Should_save_another_one =() => repo.AssertWasCalled(o => o.Save(Arg<AnotherOne>.Is.Anything)); 
} 
+0

Modül düzeyinde bir SomethingModel oluşturmak için o kadar ileri gidebilirim ki, aslında depolanmak üzere depoya gönderilmekte olduğunu doğrulayabilirsiniz. – leebrandt

+0

Teşekkürler Lee. Seninkini test ettikten ve benimkiyle karşılaştırdıktan sonra sorunu buldum. Yukarıdaki tam sonucu yayınladım. – Nathan

1

herkes sayarlar gibi görünüyor nokta bir "denirdi assert" gerçekleştirmek için saplama gerekmez olmasıdır. Ve yazdığınız şekilde, Arg<T>.Is.Anything, türü yok sayılır. Jenerik kısıtlamaları doğrulamıyorsunuz. Arg<T>.Is.TypeOf<T>'u kullanmak istiyorsunuz. Daha fazla bilgi için documentation'a bakın.

----------------------------------------------- 
| Arg<T>.Is |        | 
=============================================== 
| Anything() | No constraints    | 
----------------------------------------------- 
| TypeOf<T>() | Argument is of a certain type | 
----------------------------------------------- 

Sizin Sabit kod parçacığı hala çok karmaşıktır. "Arandığında" kaydedeceğiniz data nesnesini kullanmıyorsunuz. Ve basit bir "assert" denemek için ona ihtiyacınız yok.

@ leebrandt'ın kodu, otomobilin içine konmadan, doğru ve basit bir şekilde görünüyor.

İlgili konular