Хорошим доказательством того, что Checked Exception не нужны, являются:
Я был бы счастлив, если бы java предоставил мне выбор , что использовать при работе с основными библиотеками, такими как I / O. Like предоставляет две копии одних и тех же классов - один обернут в RuntimeEception. Тогда мы можем сравнить, что люди будут использовать . На данный момент, тем не менее, многим лучше пойти на какую-то платформу поверх Java или другой язык. Как и Скала, JRuby, что угодно. Многие просто верят, что СОЛНЦЕ было правильно.
Just to be clear, you need to differenciate between UNIT testing (test a module with no implied dependencies on other modules) and app testing (test parts of application).
For the former, you need a mocking framework (I'm only familiar with Perl ones, but i'm sure they exist in Java/C#). A sign of a good framework would be ability to take a running app, RECORD all the method calls/returns, and then mock the selected methods (e.g. the ones you are not testing in this specific unit test) using recorded data. Для хороших модульных тестов вы ДОЛЖНЫ издеваться над каждой внешней зависимостью - например, без обращений к файловой системе, без обращений к БД или другим уровням доступа к данным, если это не то, что вы тестируете, и т. Д.
Для последних - та же самая насмешливая структура полезно, плюс возможность создавать наборы тестовых данных (которые можно сбросить для каждого теста). Данные, которые будут загружены для тестов, могут находиться в любом автономном хранилище, из которого вы можете загрузить - файлы BCP для данных Sybase DB, XML, все, что вам нравится. Мы используем как BCP, так и XML.
Обратите внимание, что такого рода тестирование «данных нагрузочного теста в БД» ЗНАЧИТЕЛЬНО проще, если общая структура вашей компании допускает - или, скорее, применяет - API «Каково настоящее имя таблицы БД для этого псевдонима таблицы». Таким образом, вы можете заставить ваше приложение просматривать клонированный "тест"
Не отвечая напрямую на вопрос, но один из способов ограничить количество тестов, которые должны использовать фиктивные данные, - это использовать фреймворк для создания фиктивных объектов, которые можно использовать для имитации поведения любого зависимости, которые у вас есть в классе.
Я обнаружил, что, используя фиктивные объекты, а не конкретную конкретную реализацию, вы можете резко сократить объем реальных данных, которые вам нужно использовать, поскольку имитирующие объекты не обрабатывают данные, которые вы им передаете. Они просто работают именно так, как вы от них хотите.
Я все еще уверен, что вам, вероятно, нужны фиктивные данные во многих случаях, поэтому извиняюсь, если вы уже используете или знаете о фреймворках для имитации.
Я использую шаблон репозитория и имею фиктивный репозиторий, который создается с помощью рассматриваемых модульных тестов, он предоставляет известный набор данных, который включает примеры, которые находятся в пределах и вне диапазона для различных полей.
Это означает, что я могу протестировать свой код без изменений, предоставив экземпляр репозитория из тестового модуля для тестирования или производственного репозитория во время выполнения (через внедрение зависимостей (Castle)).
Я не знаю хорошей веб-ссылки для этого, но я многому научился из книги Стивена Сандерсона Professional ASP.NET MVC 1.0, опубликованной Apress. Подход MVC, естественно, обеспечивает разделение проблем, необходимое для того, чтобы ваше тестирование могло работать с меньшим количеством зависимостей.
Основные элементы заключаются в том, что ваш репозиторий реализует интерфейс для доступа к данным, этот же интерфейс затем реализуется поддельным репозиторием, который вы создаете в своем тестовом проекте.
В моем текущем проекте у меня есть такой интерфейс:
namespace myProject.Abstract
{
public interface ISeriesRepository
{
IQueryable<Series> Series { get; }
}
}
] Это реализовано как мой репозиторий живых данных (с использованием Linq to SQL), а также как поддельный репозиторий, таким образом:
namespace myProject.Tests.Respository
{
class FakeRepository : ISeriesRepository
{
private static IQueryable<Series> fakeSeries = new List<Series> {
new Series { id = 1, name = "Series1", openingDate = new DateTime(2001,1,1) },
new Series { id = 2, name = "Series2", openingDate = new DateTime(2002,1,30),
...
new Series { id = 10, name = "Series10", openingDate = new DateTime(2001,5,5)
}.AsQueryable();
public IQueryable<Series> Series
{
get { return fakeSeries; }
}
}
}
Затем создается экземпляр класса, потребляющего данные, передавая ссылку на репозиторий конструктору:
namespace myProject
{
public class SeriesProcessor
{
private ISeriesRepository seriesRepository;
public void SeriesProcessor(ISeriesRepository seriesRepository)
{
this.seriesRepository = seriesRepository;
}
public IQueryable<Series> GetCurrentSeries()
{
return from s in seriesRepository.Series
where s.openingDate.Date <= DateTime.Now.Date
select s;
}
}
}
Затем в моих тестах Я могу подойти к этому так:
namespace myProject.Tests
{
[TestClass]
public class SeriesTests
{
[TestMethod]
public void Meaningful_Test_Name()
{
// Arrange
SeriesProcessor processor = new SeriesProcessor(new FakeRepository());
// Act
IQueryable<Series> currentSeries = processor.GetCurrentSeries();
// Assert
Assert.AreEqual(currentSeries.Count(), 10);
}
}
}
Затем посмотрите CastleWindsor, чтобы узнать об инверсии подхода к управлению вашим живым проектом, чтобы ваш производственный код мог автоматически создавать экземпляр вашего живого репозитория посредством внедрения зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.
тот же самый интерфейс затем реализуется поддельным репозиторием, который вы создаете в своем тестовом проекте.В моем текущем проекте у меня есть такой интерфейс:
namespace myProject.Abstract
{
public interface ISeriesRepository
{
IQueryable<Series> Series { get; }
}
}
Он реализован как мой репозиторий живых данных (с использованием Linq to SQL) и также фальшивый репозиторий, например:
namespace myProject.Tests.Respository
{
class FakeRepository : ISeriesRepository
{
private static IQueryable<Series> fakeSeries = new List<Series> {
new Series { id = 1, name = "Series1", openingDate = new DateTime(2001,1,1) },
new Series { id = 2, name = "Series2", openingDate = new DateTime(2002,1,30),
...
new Series { id = 10, name = "Series10", openingDate = new DateTime(2001,5,5)
}.AsQueryable();
public IQueryable<Series> Series
{
get { return fakeSeries; }
}
}
}
Затем создается экземпляр класса, потребляющего данные, передавая ссылку на репозиторий конструктору:
namespace myProject
{
public class SeriesProcessor
{
private ISeriesRepository seriesRepository;
public void SeriesProcessor(ISeriesRepository seriesRepository)
{
this.seriesRepository = seriesRepository;
}
public IQueryable<Series> GetCurrentSeries()
{
return from s in seriesRepository.Series
where s.openingDate.Date <= DateTime.Now.Date
select s;
}
}
}
Затем в моих тестах я могу подойти к нему так:
namespace myProject.Tests
{
[TestClass]
public class SeriesTests
{
[TestMethod]
public void Meaningful_Test_Name()
{
// Arrange
SeriesProcessor processor = new SeriesProcessor(new FakeRepository());
// Act
IQueryable<Series> currentSeries = processor.GetCurrentSeries();
// Assert
Assert.AreEqual(currentSeries.Count(), 10);
}
}
}
Затем посмотрите CastleWindsor для инверсии подход к управлению вашим живым проектом, позволяющий производственному коду автоматически создавать экземпляр вашего живого репозитория посредством внедрения зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.
тот же самый интерфейс затем реализуется поддельным репозиторием, который вы создаете в своем тестовом проекте.В моем текущем проекте у меня есть такой интерфейс:
namespace myProject.Abstract
{
public interface ISeriesRepository
{
IQueryable<Series> Series { get; }
}
}
Он реализован как мой репозиторий живых данных (с использованием Linq to SQL) и также фальшивый репозиторий, например:
namespace myProject.Tests.Respository
{
class FakeRepository : ISeriesRepository
{
private static IQueryable<Series> fakeSeries = new List<Series> {
new Series { id = 1, name = "Series1", openingDate = new DateTime(2001,1,1) },
new Series { id = 2, name = "Series2", openingDate = new DateTime(2002,1,30),
...
new Series { id = 10, name = "Series10", openingDate = new DateTime(2001,5,5)
}.AsQueryable();
public IQueryable<Series> Series
{
get { return fakeSeries; }
}
}
}
Затем создается экземпляр класса, потребляющего данные, передавая ссылку на репозиторий конструктору:
namespace myProject
{
public class SeriesProcessor
{
private ISeriesRepository seriesRepository;
public void SeriesProcessor(ISeriesRepository seriesRepository)
{
this.seriesRepository = seriesRepository;
}
public IQueryable<Series> GetCurrentSeries()
{
return from s in seriesRepository.Series
where s.openingDate.Date <= DateTime.Now.Date
select s;
}
}
}
Затем в моих тестах я могу подойти к нему так:
namespace myProject.Tests
{
[TestClass]
public class SeriesTests
{
[TestMethod]
public void Meaningful_Test_Name()
{
// Arrange
SeriesProcessor processor = new SeriesProcessor(new FakeRepository());
// Act
IQueryable<Series> currentSeries = processor.GetCurrentSeries();
// Assert
Assert.AreEqual(currentSeries.Count(), 10);
}
}
}
Затем посмотрите CastleWindsor для инверсии подход к управлению вашим живым проектом, позволяющий производственному коду автоматически создавать экземпляр вашего живого репозитория посредством внедрения зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.
namespace myProject.Abstract
{
public interface ISeriesRepository
{
IQueryable<Series> Series { get; }
}
}
Это реализовано как мой репозиторий в реальном времени (с использованием Linq to SQL), так и как поддельный репозиторий, например:
namespace myProject.Tests.Respository
{
class FakeRepository : ISeriesRepository
{
private static IQueryable<Series> fakeSeries = new List<Series> {
new Series { id = 1, name = "Series1", openingDate = new DateTime(2001,1,1) },
new Series { id = 2, name = "Series2", openingDate = new DateTime(2002,1,30),
...
new Series { id = 10, name = "Series10", openingDate = new DateTime(2001,5,5)
}.AsQueryable();
public IQueryable<Series> Series
{
get { return fakeSeries; }
}
}
}
Затем создается экземпляр класса, потребляющего данные, с передачей ссылки на репозиторий конструктору:
namespace myProject
{
public class SeriesProcessor
{
private ISeriesRepository seriesRepository;
public void SeriesProcessor(ISeriesRepository seriesRepository)
{
this.seriesRepository = seriesRepository;
}
public IQueryable<Series> GetCurrentSeries()
{
return from s in seriesRepository.Series
where s.openingDate.Date <= DateTime.Now.Date
select s;
}
}
}
Затем в в моих тестах я могу подойти к этому так:
namespace myProject.Tests
{
[TestClass]
public class SeriesTests
{
[TestMethod]
public void Meaningful_Test_Name()
{
// Arrange
SeriesProcessor processor = new SeriesProcessor(new FakeRepository());
// Act
IQueryable<Series> currentSeries = processor.GetCurrentSeries();
// Assert
Assert.AreEqual(currentSeries.Count(), 10);
}
}
}
Затем посмотрите на CastleWindsor, чтобы узнать об инверсии управления вашим живым проектом, чтобы ваш производственный код мог автоматически создавать экземпляр вашего живого репозитория через внедрение зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.
namespace myProject.Abstract
{
public interface ISeriesRepository
{
IQueryable<Series> Series { get; }
}
}
Это реализовано как мой репозиторий в реальном времени (с использованием Linq to SQL), так и как поддельный репозиторий, например:
namespace myProject.Tests.Respository
{
class FakeRepository : ISeriesRepository
{
private static IQueryable<Series> fakeSeries = new List<Series> {
new Series { id = 1, name = "Series1", openingDate = new DateTime(2001,1,1) },
new Series { id = 2, name = "Series2", openingDate = new DateTime(2002,1,30),
...
new Series { id = 10, name = "Series10", openingDate = new DateTime(2001,5,5)
}.AsQueryable();
public IQueryable<Series> Series
{
get { return fakeSeries; }
}
}
}
Затем создается экземпляр класса, потребляющего данные, с передачей ссылки на репозиторий конструктору:
namespace myProject
{
public class SeriesProcessor
{
private ISeriesRepository seriesRepository;
public void SeriesProcessor(ISeriesRepository seriesRepository)
{
this.seriesRepository = seriesRepository;
}
public IQueryable<Series> GetCurrentSeries()
{
return from s in seriesRepository.Series
where s.openingDate.Date <= DateTime.Now.Date
select s;
}
}
}
Затем в в моих тестах я могу подойти к этому так:
namespace myProject.Tests
{
[TestClass]
public class SeriesTests
{
[TestMethod]
public void Meaningful_Test_Name()
{
// Arrange
SeriesProcessor processor = new SeriesProcessor(new FakeRepository());
// Act
IQueryable<Series> currentSeries = processor.GetCurrentSeries();
// Assert
Assert.AreEqual(currentSeries.Count(), 10);
}
}
}
Затем посмотрите на CastleWindsor, чтобы узнать об инверсии управления вашим живым проектом, чтобы ваш производственный код мог автоматически создавать экземпляр вашего живого репозитория через внедрение зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.
namespace myProject.Tests
{
[TestClass]
public class SeriesTests
{
[TestMethod]
public void Meaningful_Test_Name()
{
// Arrange
SeriesProcessor processor = new SeriesProcessor(new FakeRepository());
// Act
IQueryable<Series> currentSeries = processor.GetCurrentSeries();
// Assert
Assert.AreEqual(currentSeries.Count(), 10);
}
}
}
Затем посмотрите на CastleWindsor, где можно найти подход к инверсии управления для вашего живого проекта, чтобы позволить производственному коду автоматически создавать экземпляр вашего живого репозитория посредством внедрения зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.
namespace myProject.Tests
{
[TestClass]
public class SeriesTests
{
[TestMethod]
public void Meaningful_Test_Name()
{
// Arrange
SeriesProcessor processor = new SeriesProcessor(new FakeRepository());
// Act
IQueryable<Series> currentSeries = processor.GetCurrentSeries();
// Assert
Assert.AreEqual(currentSeries.Count(), 10);
}
}
}
Затем посмотрите на CastleWindsor, где можно найти подход к инверсии управления для вашего живого проекта, чтобы позволить производственному коду автоматически создавать экземпляр вашего живого репозитория посредством внедрения зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.
Ваш код в том виде, в каком он написан, не компилируется. Я сделал несколько «предположений» о том, что вы хотели сделать, и изменил код.
Подводя итог, вы можете вызвать правильную функцию, явно указав тип параметра функции:
connect<double> (&GApp::foo);
Если методы соединения являются членами шаблона класса, то необходимо указать тип класса только один раз:
template <typename T> class A
{
public:
template<class Arg1>
void connect(void (T::*f)(Arg1))
{
//Do some stuff
}
void connect(void (T::*f)())
{
//Do some stuff
}
};
class GApp
{
public:
void foo() {}
void foo(double d) {}
};
int main ()
{
A<GApp> a;
a.connect (&GApp::foo); // foo ()
a.connect<double> (&GApp::foo); // foo (double)
}
UPDATE:
В ответ на новый пример кода передается вся информация. «Редким» случаем является 'signal_void ', поскольку здесь сигнал имеет аргумент шаблона, а функция-член - нет. Поэтому мы рассматриваем этот пример отдельно, и на этом все готово. Теперь компилируется следующее: