Domanda

Sto cercando di imparare la sintassi Rhino Mocks AAA, e sto avendo problemi a far valere un certo metodo (con qualsiasi valore di argomento) è stato chiamato. Sto utilizzando Machine.Specifications come il mio framework di test.

Questo particolare metodo è generico e voglio fare in modo che è stato chiamato tre volte con tre tipi diversi.

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

I spense la funzione per ogni tipo. Ma sto ottenendo un risultato interessante. (Qui di seguito)

[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));
}

Il risultato è di due eccezioni e un pass.

La prima chiamata getta:

  

System.InvalidOperationException: Non ci sono aspettative erano configurazione da verificare, in modo che la chiamata al metodo in azione è un virtuale (C #) / superabile (VB.Net) chiamata al metodo

Il secondo getta:

  

System.InvalidOperationException: Usa Arg solo all'interno di un metodo di finta chiamata durante la registrazione. Previsto, 2 sono stati definiti 1 argomenti.

Il terzo passa ... per qualche strana ragione.

Ho anche provato ad utilizzare GenerateMock () con aspettarsi in mia messa a punto e l'utilizzo di GenerateStub () con Stub. Entrambi finirono con lo stesso identico risultato. Ho devi fare qualcosa di sbagliato.

sto usando: MachineSpec 0.3.0.0 e 3.6.0.0 RhinoMocks

Tutte le idee?

----- FISSO ----------

Ecco il completo (versione di lavoro) con l'aiuto di Lee. Sto usando uno strato (non LINQ) in più. Il mio problema reale era che uno dei miei test riutilizzato la variabile lambda sbagliato nel codice vero e non in linea.     Si Should_do_something = () => repo.AssertWasCalled ( o => repo .save (dati)); // cattivo lambda

Quindi, ecco un campione del test corretto per riferimento.

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());
        }
    }
}
È stato utile?

Soluzione

dare una prova.

[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));
}

Altri suggerimenti

Il punto che tutti sembrano essere sorvolare è che si Non è necessario stub al fine di eseguire un "assert è stato chiamato". E, il modo in cui lo avete scritto, Arg<T>.Is.Anything, sarà ignorare il tipo. Non stai verificando i vincoli generici. Si desidera utilizzare Arg<T>.Is.TypeOf<T>. Controllare il documentazione per ulteriori dettagli.

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

Il Fisso frammento di codice è ancora troppo complicata. Non si sta utilizzando l'oggetto data che si sta salvando in "quando viene chiamato". E non c'è bisogno che faccia un semplice "assert è stato chiamato".

@ di leebrandt sguardi di codice come corretta e semplice come si arriva, senza introdurre un contenitore automocking.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top