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

У меня есть Mocking.sln который имеет два проекта: Student (Библиотека классов) и StudentStat (Консольное приложение)

Student Проект имеет следующие детали:

    private static Dictionary<int, int> GetStudentData()
        {
            // Key: Student ID Value: Total marks(marks in math + marks in physics)
            Dictionary<int, int> studentResultDict = new Dictionary<int, int>();

            using (SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=myDB;Integrated Security=true"))
            {
                con.Open();
                string cmdStr = "Select * from Student";
                using (SqlCommand cmd = new SqlCommand(cmdStr, con))
                {
                    using (SqlDataReader reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            studentResultDict.Add((int)reader["ID"], (int)reader["MarksInMath"] + (int)reader["MarksInPhysics"]);
                        }
                    }
                }
            }

            return studentResultDict;
        }

     public static void CalculateTotalMarks()
        {
            Dictionary<int, int> studentResultDict = GetStudentData();
            foreach (var item in studentResultDict)
            {
                Console.WriteLine("{0}\t{1}", item.Key, item.Value);
            }
        }

StudentStat Проект имеет следующие детали:

class Program
    {
        static void Main(string[] args)
        {
            StudentInfo.CalculateTotalMarks();
        }
    }

это GetStudentData() метод чтения деталей из БД и вывода деталей. Предположим, это мой рабочий код, и у меня нет разрешения что-либо менять.

У меня перегруженная версия GetStudentData() который принимает filePath в качестве параметра и читает подробности из текстового файла. Ниже приведен метод:

private static Dictionary<int, int> GetStudentData(string filepath)
    {
        Dictionary<int, int> studentResultDict = new Dictionary<int, int>();
        foreach (var item in File.ReadAllLines(filepath))
        {
            string[] data = item.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
            studentResultDict.Add(Convert.ToInt32(data[0]), Convert.ToInt32(data[1]) + Convert.ToInt32(data[2]));
        }

        return studentResultDict;
    }

Теперь, когда я звоню StudentInfo.CalculateTotalMarks() в StudentStat.exeЯ хочу это перегружено GetStudentData(string filepath) будет вызван вместо другого метода (который читает данные из БД) и покажет мне вывод.

Я слышал, что это будет возможно с помощью NMock3, но я понятия не имею об этом. Можете ли вы поделиться примерами кода соем.. Это поможет мне узнать NMock3 также. Любая помощь приветствуется...

1 ответ

Вы можете использовать тестовую разработку, что вам нужно сделать, это провести рефакторинг кода, который у вас есть, и реализовать сегрегацию интерфейса, которая является частью принципа SOLID, я рекомендую вам прочитать блог Роя Ошерова, который является отцом TDD, я выучил TDD, просто прочитав книгу об искусстве модульного тестирования (оно может быть уже устаревшим), но в любом случае, в двух словах, вам нужно разделить код, отделить реализации и просто определить для него контракт.,

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

interface IStudentService{
   Dictionary<int, int> GetStudentData() 
}

и тогда вы могли бы иметь две разные реализации

Для простоты я просто собираюсь скопировать и вставить ваш код SQL, но вы должны иметь в виду, что команды SQL также должны рассматриваться как зависимости в вашем подходе TDD.

public class DBStudentService:IStudentService{

    public Dictionary<int, int> GetStudentData()
    {
    // Key: Student ID Value: Total marks(marks in math + marks in physics)
        Dictionary<int, int> studentResultDict = new Dictionary<int, int>();
        using (SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=myDB;Integrated Security=true"))
            {
                con.Open();
                string cmdStr = "Select * from Student";
                using (SqlCommand cmd = new SqlCommand(cmdStr, con))
                {
                    using (SqlDataReader reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            studentResultDict.Add((int)reader["ID"], (int)reader["MarksInMath"] + (int)reader["MarksInPhysics"]);
                        }
                    }
                }
            }

            return studentResultDict;
        }
}

а затем создать другую реализацию, скажем,

   public class FileStudentService:IStudentService{
        steing _filepath;
        Public FileStudentService(string filepath){
          _filepath = filepath;
        }

        public Dictionary<int, int> GetStudentData()
        {
            Dictionary<int, int> studentResultDict = new Dictionary<int, int>();
            foreach (var item in File.ReadAllLines(_filepath))
            {
                string[] data = item.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
                studentResultDict.Add(Convert.ToInt32(data[0]), Convert.ToInt32(data[1]) + Convert.ToInt32(data[2]));
            }

        return studentResultDict;
        }

    }

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

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

лично мне нравится структура карты и простой Injector, регистрация вашей реализации очень проста ( с использованием SI)

var container = new Container();
Configure the container (register)
container.Register<IStudentService, FileStudentService>();

а затем вы можете внедрить свой сервис, используя конструктор инъекций в вашу программу, и это должно сделать свое дело

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

ура!

Другие вопросы по тегам