Как AssertWasCalled универсальный метод с тремя различными типами, используя RhinoMocks? - PullRequest
1 голос
/ 19 ноября 2010

Я пытаюсь выучить синтаксис Rhino Mocks AAA, и у меня возникают проблемы с утверждением, что был вызван определенный метод (с любым значением аргумента).Я использую Machine.Specification в качестве основы тестирования.

Этот конкретный метод является общим, и я хочу убедиться, что он вызывался три раза с тремя разными типами.

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

Я обозначил функцию для каждого типа.Но я получаю интересный результат.(ниже)

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

Результат - два исключения и проход.

Первый бросок вызова:

System.InvalidOperationException: не были настроены ожидания для проверки, убедитесь, что вызов метода в действии является виртуальным (C #) / переопределяемым (VB)..Net) вызов метода

Второй бросает:

System.InvalidOperationException: Использовать ТОЛЬКО Arg в пределах ложного вызова метода во время записи.Ожидается 1 аргумент, 2 определены.

Третий аргумент проходит ... по какой-то странной причине.

Я также пытался использовать GenerateMock () с Expect в моей настройке, а также GenerateStub () с Stub.Оба оказались с одинаковым результатом.Я должен делать что-то не так.

Я использую: MachineSpec 0.3.0.0 и RhinoMocks 3.6.0.0

Есть идеи?

----- ИСПРАВЛЕНО ----------

Вот полная (рабочая версия) с помощью Ли.Я использую дополнительный (не linq) слой.Моя настоящая проблема заключалась в том, что один из моих тестов повторно использовал неправильную лямбда-переменную в автономном реальном коде.Он должен_д_сомать = () => repo.AssertWasCalled ( o => репо .Save (данные));// плохая лямбда

Итак, вот пример правильного теста для справки.

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

Ответы [ 2 ]

1 голос
/ 20 февраля 2013

Дело в том, что все, похоже, скрывают, что не нужно заглывать , чтобы выполнить "assert было вызвано". И, как вы это написали, Arg<T>.Is.Anything, он будет игнорировать тип. Вы не проверяете какие-либо общие ограничения. Вы хотите использовать Arg<T>.Is.TypeOf<T>. Обратитесь к документации для получения более подробной информации.

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

Ваш Исправленный фрагмент кода все еще слишком сложен. Вы не используете объект data, который сохраняете в «при вызове». И вам это не нужно, чтобы сделать простое «утверждение было названо».

@ Код leebrandt выглядит настолько же корректным и простым, насколько это возможно, без введения контейнера для автоматической блокировки.

0 голосов
/ 19 ноября 2010

Дайте этому попытку.

[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));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...