Как выполнить модульное тестирование 2 последовательных вызовов одного и того же метода с различными типами параметров - PullRequest
0 голосов
/ 07 февраля 2019

Работа с C # .NetFrameWork 4.7, Moq 1.4

Я тестирую метод, который выполняет 2 интерфейсных вызова.Метод интерфейса принимает 1 параметр, и этот параметр также является интерфейсом.С трудом проверяя это, Moq выдает ошибки приведения.

2 последовательных вызова со следующей сигнатурой:

InterfaceUnderTest.MethodUnderTest(IEnumerable<IParamInterface>)

Полный пример кода можно найти здесь, на github: https://github.com/JayZhang727/UnitTestingInterfaceParams

Ниже приведена базовая структура:

импортируемые интерфейсы и реализации, которые я не могу изменить:

public interface IWorkInterface
{
    string DoWork(IEnumerable<IParamInterface> para);
}

public interface IParamInterface
{
    IParamDataInterface GetParamData();
}

public interface IParamDataInterface
{
    string Id { get; set; }
}

public class ParamClass<T> : IParamInterface where T : IParamDataInterface
{
    public T ParamData { get; set; }

    public ParamClass()
    {

    }

    public ParamClass(T para)
    {
        this.ParamData = para;
    }

    public IParamDataInterface GetParamData()
    {
        return ParamData;
    }
}

public class ParamClassA : IParamDataInterface
{
    public ParamClassA()
    {
        this.Id = "Id";
        this.ParamClassAVar = 123;
    }

    public string Id { get; set; }

    public int ParamClassAVar { get; set; }

}

public class ParamClassB : IParamDataInterface
{
    public ParamClassB()
    {
        this.Id = "Id";
        this.ParamClassBVar = "not 123";
    }

    public string Id { get; set; }

    public string ParamClassBVar { get; set; }

}

Вот тестируемый класс:

public ClassUnderTest(IWorkInterface workInt)
{
    this.WorkClient = workInt;
}

public IWorkInterface WorkClient { get; set; }

public string MethodUnderTest()
{
    var result = string.Empty;

    //Class A is an implementation of IParamDataInterface
    var a = new ParamClassA();
    var theParamA = new ParamClass<ParamClassA>(a);
    var listA = new List<IParamInterface>();
    listA.Add(theParamA);

    result = WorkClient.DoWork(listA);

    //Class B is also an implementation of IParamDataInterface
    var b = new ParamClassB();
    var theParamB = new ParamClass<ParamClassB>(b);
    var listB = new List<IParamInterface>();
    listB.Add(theParamB);

    result = result + WorkClient.DoWork(listB);

    return result;
}

Вот тестовые вызовы, которые я пробовал:

private Mock<IWorkInterface> mockClient;

[TestMethod()]
public void DoWorkTest()
{
    mockClient = new Mock<IWorkInterface>(MockBehavior.Strict);
    var target = new ClassUnderTest(mockClient.Object);

    var mockSquence = new MockSequence();

    mockClient.InSequence(mockSquence).Setup(ec => ec.DoWork(It.Is<List<IParamInterface>>(el => ((ParamClassA)((ParamClass<ParamClassA>)el[0]).GetParamData()).ParamClassAVar == 123))).Returns("123");

    mockClient.InSequence(mockSquence).Setup(ec => ec.DoWork(It.Is<List<IParamInterface>>(el => ((ParamClassB)((ParamClass<ParamClassB>)el[0]).GetParamData()).ParamClassBVar == "not 123"))).Returns("not 123");

    //act
    target.MethodUnderTest();


    //assert
    mockClient.VerifyAll();
}

Я получаю ошибки о невозможности приведения из класса A в класс B:

Message: Test method ClassUnderTesting.UnitTests.ClassUnderTestingTests.DoWorkTest threw exception: 
System.InvalidCastException: Unable to cast object of type 'ClassUnderTesting.ParamClass`1[ClassUnderTesting.ParamClassA]' to type 'ClassUnderTesting.ParamClass`1[ClassUnderTesting.ParamClassB]'.

Кажется, что Moqне делая это последовательно и по какой-то причине вторая установка превосходит первую настройку, и последовательность, похоже, не помогает.Кто-нибудь знает, как мне настроить и проверить эти 2 звонка?

1 Ответ

0 голосов
/ 07 февраля 2019

Я бы сделал это без последовательности.Просто настройте свои ожидания так, чтобы при вызове DoWork с помощью ParamClassA он возвращал «123», а при вызове с ParamClassB - «не 123».

Обратите внимание, что первое ожидание не завершится, еслиему не дано ParamClassA: оно просто не будет совпадать (а также второе и ParamClassB).

mockClient
    .Setup(ec => ec.DoWork(
        It.Is<List<IParamInterface>>(el => el[0] is ParamClass<ParamClassA> && ((ParamClass<ParamClassA>)el[0]).ParamData.ParamClassAVar == 123)
    ))
    .Returns("123");

mockClient
    .Setup(ec => ec.DoWork(
        It.Is<List<IParamInterface>>(el => el[0] is ParamClass<ParamClassB> && ((ParamClass<ParamClassB>)el[0]).ParamData.ParamClassBVar == "not 123")
    ))
    .Returns("not 123");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...