Как выполнить модульное тестирование неизменяемых конструкторов классов? - PullRequest
1 голос
/ 25 сентября 2008

У меня есть неизменный класс с некоторыми закрытыми полями, которые устанавливаются во время выполнения конструктора. Я хочу провести модульное тестирование этого конструктора, но я не уверен, что в этом случае "лучшая практика".

Простой пример

Этот класс определен в Assembly1:

public class Class2Test
{
    private readonly string _StringProperty;

    public Class2Test()
    {
        _StringProperty = ConfigurationManager.AppSettings["stringProperty"];
    }
}

Этот класс определен в Assembly2:

[TestClass]
public class TestClass
{
    [TestMethod]
    public void Class2Test_Default_Constructor()
    {
        Class2Test x = new Class2Test();
        //what do I assert to validate that the field was set properly?
    }
}

РЕДАКТИРОВАТЬ 1 : я ответил на этот вопрос с потенциальным решением, но я не уверен, что это "правильный путь". Поэтому, если вы считаете, что у вас есть идея получше, пожалуйста, напишите ее.

Этот пример не стоит проверять, но предположим, что конструктор имеет более сложную логику. Является ли лучший подход, чтобы избежать тестирования конструктора и просто предположить, что он работает, если все тесты для методов в классе работают?

РЕДАКТИРОВАТЬ 2 : Похоже, я сделал образец немного проще. Я обновил его в более разумной ситуации.

Ответы [ 3 ]

8 голосов
/ 25 сентября 2008

Ничего, если только вы не используете это поле. Вы не хотите переусердствовать с помощью тестов. Другими словами, нет необходимости проверять, работает ли оператор присваивания.

Если вы используете это поле в методе или чем-то еще, вызовите этот метод и подтвердите его.

Редактировать:

предположим, что конструктор имеет более сложную логику

Вы не должны выполнять какую-либо логику в конструкторах.

Редактировать 2:

public Class2Test()
{
     _StringProperty = ConfigurationManager.AppSettings["stringProperty"];
}

Не делай этого! =) Ваш простой модульный тест теперь стал интеграционным тестом, потому что он зависит от успешной работы более чем одного класса. Напишите класс, который обрабатывает значения конфигурации. Имя WebConfigSettingsReader может быть именем, и оно должно инкапсулировать вызов ConfigurationManager.AppSettings. Передайте экземпляр этого класса SettingsReader в конструктор Class2Test. Затем, в своем модульном тесте , вы можете смоделировать ваш WebConfigSettingsReader и заглушить ответ на любые вызовы, которые вы можете сделать ему.

1 голос
/ 25 сентября 2008

При редактировании у вас теперь есть зависимость от ConfigurationManager, которую сложно протестировать.

Одно из предложений - извлечь интерфейс к нему, а затем заставить cort Class2Test принять экземпляр IConfigManager в качестве параметра. Теперь вы можете использовать поддельный / фиктивный объект, чтобы установить его состояние, так что любые методы, которые полагаются на Конфигурацию, могут быть протестированы, чтобы увидеть, используют ли они правильные значения ...

    public interface IConfigManager
    {
        string FooSetting { get; set; }
    }

    public class Class2Test
    {
        private IConfigManager _config;
        public Class2Test(IConfigManager configManager)
        {
            _config = configManager;   
        }

        public void methodToTest()
        {
            //do something important with ConfigManager.FooSetting
            var important = _config.FooSetting;
            return important;
        }
    }

    [TestClass]
    public class When_doing_something_important
    {
        [TestMethod]
        public void Should_use_configuration_values()
        {
            IConfigManager fake = new FakeConfigurationManager();
            //setup state
            fake.FooSetting = "foo";
            var sut = new Class2Test(fake);
            Assert.AreEqual("foo", sut.methodToTest());
        }
    }
1 голос
/ 25 сентября 2008

Я правильно включил [InternalsVisibleTo] в Assembly1 (код), чтобы были установлены доверительные отношения с Assembly2 (тесты).

public class Class2Test
{
    private readonly string _StringProperty;
    internal string StringProperty { get { return _StringProperty; } }

    public Class2Test(string stringProperty)
    {
        _StringProperty = stringProperty;
    }
}

Что позволяет мне утверждать это:

Assert.AreEqual(x.StringProperty, "something");

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

Дополнительные мысли будут с благодарностью.

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