Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

Вопрос Программисту - как заменить этот синглтон на его мок?

08.11.18 21:31
Вопрос Программисту - как заменить этот синглтон на его мок?
 
dymanoid знакомое лицо
dymanoid

Вопрос специально к юзеру Программист.

Ты утверждаешь, что сделав сеттер точки доступа к синглтону internal, можно сделать этот синглтон mockable.

Моя фраза:

Замена модификатора сеттера на internal никаким образом не поможет синглтон сделать mockable.

Твой ответ:

Ошибаешься.

Ну и дальше пошла от тебя какая-то пурга, мерянье пиписьками:

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

Сначала по поводу "привести рабочий код синглтона". Да *б твою ж мать! Ругаться грязно хочется. Меня кто-то просил рабочий код синглтона приводить? Ты вообще понимаешь разницу между схематичным наброском и рабочим кодом? Ты на StackOverflow тоже ко всем вопросам и ответам комменты такие пишешь, что у них там код нерабочий, потому что половины не хватает? Я же написал - это каракули, чтобы продемонстрировать, сколько кривых зависимостей может быть.


А то получается такой диалог:

dymanoid: Вот схема ДТП. Объясните мне, как вообще этот чувак на зелёной тачке мог сюда повернуть?

Программист: Да у тебя зелёная тачка вообще никуда не поедет, ты там колёса не нарисовал.

dymanoid: Да при чём тут колёса? Я вообще на автозаводе работаю и всё могу про колёса рассказать. Ты лучше посмотри на взаимное положение тачек на картинке!

Программист: Всё понятно. Рабочую картинку авто ты нарисовать не смог. Не знаю, чего ты там про колёса можешь объяснить. В отличие от тебя, я стопицот видов колёс уже нарисовал и точно знаю, где на них размерность покрышек находится.


Я могу привести тебе как минимум 7 разновидностей рабочего кода синглтонов и рассказать про все их достоинства, недостатки, быстродействие и до фига всего ещё. Но не в этой теме.


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


Предположим, я тест хочу на CI-серваке запустить, поэтому там без моков это всё не будет работать. Во-первых, логин не тот, во вторых, предположим, к базе нет доступа.


(Ну и, конечно, это абсолютно дурацкое решение делать сеттер в синглтоне internal - открываем ворота для всех подряд в сборке, мол, меняйте объект, когда хотите. Уже предвкушаю ответы: "да никто не будет этого делать", "надо в комментариях написать, что только в тестах менять можно" - прям в каком-то идеальном мире живёшь, или не работал ни разу в командах по 200 человек.)


    class UserRepository
    {
        private static readonly Lazy<UserRepository> instance = new Lazy<UserRepository>();

        public static UserRepository Instance => instance.Value;

        private UserRepository() { }

        public string CurrentUser => "get-Windows-login"; /* Здесь сложный код получения юзера */

        public object GetUserToken(string userName) => null; /* Здесь сложный код получения токена из имени */
    }

    class ConfigRepository
    {
        private static readonly Lazy<ConfigRepository> instance = new Lazy<ConfigRepository>();

        public static ConfigRepository Instance => instance.Value;

        private readonly object userToken;

        private ConfigRepository()
        {
            userToken = UserRepository.Instance.GetUserToken(UserRepository.Instance.CurrentUser);
        }

        private IEnumerable GetConfigItems()
        {
            using (var conn = new SqlConnection(Properties.Resources.ConnectionString))
            {
                using (var dbContext = new MyDbContext(conn, contextOwnsConnection: true))
                {
                    return dbContext.ConfigItems.Where(c => c.UserToken == userToken).ToList();
                }
            }
        }

        public int HowManyConfigItems(DateTime oldest)
        {
            return GetConfigItems().Count(c => c.CreationDate >= oldest);
        }
    }

    [TestClass]
    public class MyTestClass
    {
        [TestMethod]
        public void MyTestMethod()
        {
            // ну и как?
            var configItemsCount = ConfigRepository.Instance.HowManyConfigItems(DateTime.Now);

            Assert.AreEqual(42, configItemsCount);
        }
    }
 

Перейти на