Как назначить / выбрать несколько делегатов для метода «moled»? - PullRequest
2 голосов
/ 04 августа 2011

В настоящее время я проверяю кротов извне, пока жду лицензии VS 2010, и мне интересно, позволяет ли кротов мне:

  1. предоставляет возможность назначать несколько делегатов моль для метода, который может быть смоделирован, возможно, на уровне настройки тестового прибора?
  2. переключить время выполнения в моем тестовом случае, какой из моих делегатов родинки должен быть вызван для предстоящего вызова (вызовов) для изолированного метода moled?

Есть подсказки?

1 Ответ

1 голос
/ 05 августа 2011

Лучший ответ:

Гораздо логичнее и логичнее включить логическую схему в метод обхода, чем использовать две заглушки для одного и того же метода!Например, MyMethod считывает данные из трех разных файлов на диске, каждый из которых требует возврата различных фиктивных данных.Мы можем объехать System.IO.File.OpenRead и установить возвращаемое значение, проанализировав входные параметры OpenRead :

МЕТОД ТЕСТА:

[TestMethod]
[HostType("Moles")]
public void Test()
{
    System.IO.Moles.MFile.OpenReadString = filePath => {
        var mockStream = new System.IO.FileStream();
        byte[] buffer;
        switch (filePath)
        {
            case @"C:\DataFile.dat":
                mockStream.Write(buffer, 0, 0); // Populate stream
                break;
            case @"C:\TextFile.txt":
                mockStream.Write(buffer, 0, 0); // Populate stream
                break;
            case @"C:\LogFile.log":
                mockStream.Write(buffer, 0, 0); // Populate stream
                break;
        }
        return mockStream;
    };


    var target = new MyClass();
    target.MyMethod();
}

Тип цели:

using System.IO;
public class MyClass
{
    public void MyMethod()
    {
        var fileAData = File.OpenRead(@"C:\DataFile.dat");
        var fileBData = File.OpenRead(@"C:\TextFile.txt");
        var fileCData = File.OpenRead(@"C:\LogFile.log");
    }
}

Прямой ответ на ваши вопросы:

Да для # 1 : создать один тип для каждого обхода, а затем использовать каждый для желаемого поведения.И yes to # 2 : воздействовать на один случай типа родинки или другой.Это требует добавления входных параметров метода или внедрения в конструктор класса.

Например, MyMethod считывает три файла данных с диска, и вам необходимо передать обратно три разных макета данных. MyMethod требует трех параметров - явно назойливое решение.(Обратите внимание, что входные параметры имеют тип FileInfo; потому что System.IO> Файл является статическим и не может быть создан: Например:

МЕТОД ТЕСТА:

[TestMethod]
[HostType("Moles")]
public void Test()
{
    var fileInfoMoleA = new System.IO.Moles.MFileInfo();
    fileInfoMoleA.OpenRead = () => { return new FileStream(); };

    var fileInfoMoleB = new System.IO.Moles.MFileInfo();
    fileInfoMoleB.OpenRead = () => { return new FileStream(); };

    var fileInfoMoleC = new System.IO.Moles.MFileInfo();
    fileInfoMoleC.OpenRead = () => { return new FileStream(); };

    var target = new MyClass();
    target.MyMethod(fileInfoMoleA, fileInfoMoleB, fileInfoMoleC);
}

TARGET TYPE:

using System.IO;
public class MyClass
{
    // Input parameters are FileInfo type; because, System.IO.File
    // is a static class, and can not be instantiated.
    public void MyMethod(FileInfo fileInfoA, FileInfo fileInfoB, FileInfo fileInfoC)
    {
        var fileAData = fileInfoA.OpenRead();
        var fileBData = fileInfoB.OpenRead();
        var fileCData = fileInfoC.OpenRead();
    }
}

ОБНОВЛЕНИЕ:

В ответ на комментарий @Chai можно создать общие методы в рамках тестового проекта, которыеможно ссылаться как делегат обхода. Например, вы можете захотеть написать общий метод, на который может ссылаться любой модульный тест, который устанавливает множество предварительно сконфигурированных сценариев. В следующем примере показано, как параметризованный метод может бытьиспользовать творческий подход - это всего лишь вызовы методов!

ТИПЫ ЦЕЛЕЙ:

namespace PexMoleDemo
{
    public class MyClass
    {
        private MyMath _math;
        public MyClass()
        {
            _math = new MyMath() { left = 1m, right = 2m };
        }

        public decimal GetResults()
        {
            return _math.Divide();
        }
    }

    public class MyOtherClass
    {
        private MyMath _math;
        public MyOtherClass()
        {
            _math = new MyMath() { left = 100m, right = 200m };
        }

        public decimal Divide()
        {
            return _math.Divide();
        }
    }

    public class MyMath
    {
        public decimal left { get; set; }
        public decimal right { get; set; }

        public decimal Divide()
        {
            return left / right;
        }
    }
}

МЕТОДЫ ИСПЫТАНИЙ: наборы ArrangeScenarios ()обходные пути, включив параметр перечисления, что позволяет устанавливать одни и те же сценарии сухим способом на протяжении многих испытаний.

using System;
using Microsoft.Moles.Framework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PexMoleDemo;
[assembly: MoledAssembly("PexMoleDemo")]

namespace TestProject1
{
    [TestClass()]
    public class ProgramTest
    {
        public enum Scenarios
        {
            DivideByZero,
            MultiplyInsteadOfDivide
        }

        private void ArrangeScenario(Scenarios scenario)
        {
            switch (scenario)
            {
                case Scenarios.DivideByZero:
                    PexMoleDemo.Moles.MMyMath.AllInstances.rightGet = 
                        instance => { return 0m; };
                    break;
                case Scenarios.MultiplyInsteadOfDivide:
                    PexMoleDemo.Moles.MMyMath.AllInstances.Divide = 
                        instance => { return instance.left * instance.right; };
                    break;
                default:
                    throw new NotImplementedException("Invalid scenario.");
            }
        }

        [TestMethod]
        [HostType("Moles")]
        [ExpectedException(typeof(DivideByZeroException))]
        public void Test1()
        {
            ArrangeScenario(Scenarios.DivideByZero);
            var target = new PexMoleDemo.MyClass();

            var math = new PexMoleDemo.MyMath() { left = 1, right = 2 };
            var left = math.left;
            var right = math.right;


            var actual = target.GetResults();
        }

        [TestMethod]
        [HostType("Moles")]
        public void Test2()
        {
            ArrangeScenario(Scenarios.MultiplyInsteadOfDivide);
            // Perform some sort of test that determines if code breaks
            // when values are multiplied instead of divided.
        }

        [TestMethod]
        [HostType("Moles")]
        [ExpectedException(typeof(DivideByZeroException))]
        public void Test3()
        {
            ArrangeScenario(Scenarios.DivideByZero);
            var target = new PexMoleDemo.MyOtherClass();

            var math = new PexMoleDemo.MyMath() { left = 1, right = 2 };
            var left = math.left;
            var right = math.right;


            var actual = target.Divide();
        }

        [TestMethod]
        [HostType("Moles")]
        public void Test4()
        {
            ArrangeScenario(Scenarios.MultiplyInsteadOfDivide);
            // Perform some sort of test that determines if code breaks
            // when values are multiplied instead of divided.
        }
    }
}
...