Убедитесь, что в вызове функции передан правильный метод - PullRequest
1 голос
/ 22 февраля 2012

Мой тестовый класс принимает в своем конструкторе 2 объекта: загрузчик данных и класс, который использует данные, возвращаемые загрузчиком данных.

Интерфейс загрузчика данных имеет 2 функции: LoadCompanies () и LoadEmployees (), каждая из которых принимает параметр int и возвращает IEnumerable.

Как проверить, что тестируемый метод передает LoadCompanies () и NOT LoadEmployees () в класс потребителя данных?

Вот мой код:

[TestFixture]
public class TestingFunctionalParameters_UT
{
    [Test]
    public void Correct_Loader_Method_is_Used()
    {
        const int userId = 1;
        var companies = new[] { "c1", "c2" };
        var dataLoader = MockRepository.GenerateMock<ITestDataLoader>();
        var dataConsumer = MockRepository.GenerateMock<IDataConsumerClass>();

        var testObject = new TestClass(dataLoader, dataConsumer);

        dataConsumer.Expect(fc => fc.LoadIt(Arg<Func<IEnumerable<string>>>.Is.TypeOf)).Return(true);

        //TODO: validate that correct dataloader function was called...
        //dataLoader.Expect(dl => dl.LoadCompanies(userId)).Return(companies);

        var result = testObject.Run(userId);

        Assert.That(result, Is.True);
        dataLoader.VerifyAllExpectations();
        dataConsumer.VerifyAllExpectations();
    }
}

public class TestClass
{
    private readonly ITestDataLoader dataLoader;
    private readonly IDataConsumerClass funcClass;

    public TestClass(ITestDataLoader dataLoader, IDataConsumerClass funcClass)
    {
        this.dataLoader = dataLoader;
        this.funcClass = funcClass;
    }

    public bool Run(int userId)
    {
        Func<IEnumerable<string>> loadFn = () => dataLoader.LoadCompanies(userId);
        return funcClass.LoadIt(loadFn);
    }
}

public interface ITestDataLoader
{
    IEnumerable<string> LoadCompanies(int userId);
    IEnumerable<string> LoadEmployees(int userId);
}

public interface IDataConsumerClass
{
    bool LoadIt(Func<IEnumerable<string>> load);
}

Ответы [ 2 ]

1 голос
/ 22 февраля 2012

Вы можете создавать классы компаний и сотрудников

class Company
{
    public Company(string name)
    {
        Name = name;
    }

    public string Name { get; private set; }

    public override string ToString()
    {
        return Name;
    }
}

Сделайте то же самое для сотрудников, а затем определить свой интерфейс следующим образом

public interface ITestDataLoader   
{   
    IEnumerable<Company> LoadCompanies(int userId);   
    IEnumerable<Employee> LoadEmployees(int userId);   
}

Теперь компании и сотрудники больше не могут путаться.


РЕДАКТИРОВАТЬ:

Если у вас много таких случаев, вы можете создать общий базовый класс

class NamedItem
{
    public NamedItem(string name)
    {
        Name = name;
    }

    public string Name { get; private set; }

    public override string ToString()
    {
        return Name;
    }
}

class Company : NamedItem
{
    public Company(string name)
        : base(name)
    {
    }
}

class Employee : NamedItem
{
    public Employee (string name)
        : base(name)
    {
    }
}
0 голосов
/ 22 февраля 2012

( Редактировать : я предполагаю, что ваш пример является упрощенным, а ваша фактическая реализация - попытка проверить шаблон внедрения делегата)

Возможно, вы могли бы написать свой тест какэтот?( Отредактировано для фактической компиляции )

[Test]
public void Correct_Loader_Method_is_Used()
{
    const int userId = 1;
    var companies = new[] { "c1", "c2" };
    var dataLoader = MockRepository.GenerateMock<ITestDataLoader>();
    var dataConsumer = MockRepository.GenerateMock<IDataConsumerClass>();

    var testObject = new TestClass(dataLoader, dataConsumer);

    dataConsumer.Expect(fc => fc.LoadIt(Arg<Func<IEnumerable<string>>>.Matches(x => x().Any()))).Return(true);

    //validate that correct dataloader function was called...
    dataLoader.Expect(dl => dl.LoadCompanies(userId)).Return(companies);
    // Fails if you uncomment this line
    //dataLoader.Expect(dl => dl.LoadEmployees(userId)).Return(companies);

    var result = testObject.Run(userId);

    Assert.That(result, Is.True);
    dataLoader.VerifyAllExpectations();
    dataConsumer.VerifyAllExpectations();
}

В основном ограничение Matches () попытается выполнить метод, и если он попытается вызвать LoadEmployees (), RhinoMocks будет жаловаться, потому что он не 'у него есть определенный макет.

Обновление: обработка Action<T> делегатов

Это может быть немного менее надежно, но для Action<T> s:

public interface IDataConsumerClass
{
    bool LoadIt(Func<IEnumerable<string>> load);
    bool ExecuteIt<T>(Action<T> execute);
}

//...

dataConsumer.Expect(fc => fc.ExecuteIt(Arg<Action<int>>.Matches(x => ActionWrapper(x, userId)))).Return(true);

//...

private bool ActionWrapper<T>(Action<T> action, T arg)
{
    action(arg);
    return true;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...