Как выполнить модульное тестирование метода, который ожидает обновления объекта по ссылке? - PullRequest
2 голосов
/ 15 сентября 2009

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

В качестве примера, скажем, у меня есть класс с именем Policy.

Policy policy = new Policy();
policy.Status = Active;

Затем я передаю эту политику менеджеру политики для ее деактивации.

policyManager.InactivatePolicy(policy);

Метод политики инактивации выполняет следующие действия:

public void InactivatePolicy(Policy policy)
{
    policy.Status = Inactive;
    UpdatePolicy(policy); //saves the updated policy details via nhibernate
}

У меня проблемы с модульным тестированием этого метода DoSomething. (игнорируйте тот факт, что то, что он делает в этом примере, бесполезно)

public void DoSomething(Policy policy)
{
    Policy policy = new Policy();
    policy.Status = Active;

    policyManager.InactivatePolicy(policy);
}

Из-за того, что я делаю макет диспетчера политик, статус не становится неактивным и в результате, когда я утверждаю, что после DoSomething называется статус политика неактивна Я получил тестовый сбой, так как он все еще активен.

[Test]
public void TheStatusShouldBeInactiveWhenWeDoSomething()
{
    Mock<IPolicyManager> policyManagerMock = new Mock<PolicyManager>();
    MyClass mc = new MyClass(policyManagerMock.Object);

    Policy policy = new Policy();
    policy.Status = Active;

    mc.DoSomething(policy);

    Assert.That(policy.Status, Is.EqualTo(Inactive)); //this fails      
}

Так что я нахожусь в ситуации, когда код работает в реальности, но не в изоляции в моих модульных тестах.

Единственный способ обойти эту проблему - заставить метод InactivatePolicy менеджера политики вернуть измененный политики, чтобы я мог смоделировать ожидаемое возвращаемое значение.

public Policy InactivatePolicy(Policy policy)
{
    policy.Status = Inactive;
    UpdatePolicy(policy); //saves the updated policy details via nhibernate
    return policy;
}

[Test]
public void TheStatusShouldBeInactiveWhenWeDoSomething()
{
    Mock<IPolicyManager> policyManagerMock = new Mock<PolicyManager>();
    MyClass mc = new MyClass(policyManagerMock.Object);

    Policy expectedInactivePolicy = new Policy();
    expectedInactivePolicy.Status = Inactive;

    Policy policy = new Policy();
    policy.Status = Active;

    policyManagerMock
        .Setup(p => p.InactivatePolicy(policy))
        .Returns(expectedInactivePolicy);   

    mc.DoSomething(policy);

    Assert.That(policy.Status, Is.EqualTo(Inactive)); //this now succeeds

}

Обычно, когда я пытаюсь что-то тестировать, это признак того, что я делаю что-то не так.

Кто-нибудь знает, есть ли лучший способ сделать это? Нужно ли по существу возвращать значения, которые изначально предназначались для обновления с помощью ссылочного значения, которое было передано в метод?

Возможно, моя проблема в том, что у менеджера политики не должно быть метода InactivatePolicy, но вместо этого он должен быть в самом объекте Policy, а обновление базы данных вызывается позже?

Ответы [ 3 ]

6 голосов
/ 15 сентября 2009

Вы не должны издеваться над PolicyManager, вы должны имитировать метод UpdatePolicy, поскольку вы все еще хотите проверить функциональность метода DoSomething.

Кроме того, вы, вероятно, тестируете слишком высоко дерево.

Вы должны проверить метод InactivatePolicy () изолированно и проверить только то, что функциональность работает, а затем вам следует протестировать метод DoSomething (), снова в Isolation.

Здесь у вас есть 2 отдельные единицы кода, и у вас должны быть модульные тесты, которые проверяют каждую единицу отдельно.

0 голосов
/ 15 сентября 2009

Я думаю, что тест неверен, потому что на самом деле вы тестируете фиктивный объект и его влияние на активное состояние вашего объекта политики, а не тестируете исходный объект, и даже если тест проходит в реальном мире, PolicyManager может вести себя по-другому и вызывать DoSomething. терпеть неудачу. Может быть, вам лучше протестировать PolicyManager и его метод UpdateInactive в модульном тесте и получить Проверка целостности для проверки DoSomething вместе с реальным PolicyManager.

0 голосов
/ 15 сентября 2009

Rambling

Я не совсем понимаю.

Если вы не проверяете тот факт, что он установлен на true через NHibernate (то есть вы предполагаете, что это работает), то что вы вообще тестируете? Зачем вообще проверять, что значение установлено, учитывая, что в рабочем коде вы просто предполагаете, что это так? Даже если бы вы тривиально копировали систему, которая устанавливает ее в true, я не вижу в этом смысла, потому что это не то же самое, что производственный код.

В лучшем случае я бы подумал о том, чтобы иметь «издевательское» хранилище данных; не nHibernate, это просто ничего не делает. В этом случае он будет реализован в классе UpdatePolicy, с некоторым «MockRepo» вместо «nHibernateRepo».

Таким образом, если вы правильно настроите репо, вы увидите, что он установлен.

Хотя я бы удивился, потому что, возможно, в вашем коде nHibernate есть ошибка, и фактически все, что вы проверяете, это установка логического значения.

Резюме

Почему бы просто не создать тестовую базу данных, с которой вы можете запустить этот тест?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...