Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
2. В предыдущей статье, уважаемый mayorovp уже упоминал возможность удаления всех временных файлов при закрытии процесса, но там велась речь о решении с помощью P/Invoke. На самом деле есть стандартная обертка над этим флагом.
По моему скромному мнению, код вашего финализатора тестировать не стоит(по крайней мере с помощью unit-теста).
Не совсем понимаю, как это может помочь в случае использования Path.GetTempFileName. Не хотелось бы переходить на собственную реализация «временных» файлов.
Готов написать два теста: unit тест для проверки, что вызывается удаление файла, но мне нужет еще тест для проверки того, что файл действительно удаляется.
Кстати, «тестировать не стоит» потому что это тестируется глазками, или потому что, нет нормального способа?
This method can be called only once for each file name extension, because it will return the same name if it is called with the same extension..
try-catch вызов File.Delete в Dispose — плохо. Файл может отказаться удалиться по тем или иным причинам, а Dispose не должен (should not) кидать исключения.Dispose(false) — а именно таким обычно и бывает финализатор? Хотите протестировать финализатор? Тестируйте Dispose(false).мне нужет еще тест для проверки того, что файл действительно удаляетсяВам не нужно тестировать
File.Delete. Это уже не ваша забота. Что стоит протестировать — это факт того, что File.Delete вызывается. Для этого в Visual Studio есть Fake Assemblies.void Delete(string fileName). void Delete(string fileName) {
try {
File.Delete(fileName);
}
catch {
// Ignore all exceptions
}
}
void EnsureTempNameCreated() {
if (basePath == null) {
string tempFileName = null;
FileStream tempFileStream;
bool uniqueFile = false;
int retryCount = 5000;
do {
try {
basePath = GetTempFileName(TempDir);
string full = Path.GetFullPath(basePath);
new FileIOPermission(FileIOPermissionAccess.AllAccess, full).Demand();
// make sure the filename is unique.
tempFileName = basePath + ".tmp";
using (tempFileStream = new FileStream(tempFileName, FileMode.CreateNew, FileAccess.Write)) { }
uniqueFile = true;
}
catch (IOException e) {
retryCount--;
uint HR_ERROR_FILE_EXISTS = unchecked(((uint)0x80070000) | NativeMethods.ERROR_FILE_EXISTS);
if (retryCount == 0 || Marshal.GetHRForException(e) != HR_ERROR_FILE_EXISTS)
throw;
uniqueFile = false;
}
}while (!uniqueFile);
files.Add(tempFileName, keepFiles);
}
}
2. В чём смысл тестирования единственной строки Dispose(false) — а именно таким обычно и бывает финализатор? Хотите протестировать финализатор? Тестируйте Dispose(false).
Dispose(false). Этот факт можно тестировать статическим анализом. Соответственно, если Dispose(false) вызывает удаление файла (вы же написали тест?), то можно быть уверенным, что и финализатор тоже вызовет удаление файла, unit-тест излишен.Этот факт можно тестировать статическим анализом.
[writing|creating] custom fxcop rule.4. Unit-тест, зависимый от внешней среды (в вашем случае — файловой системы), плох.
3.
мне нужет еще тест для проверки того, что файл действительно удаляется
Вам не нужно тестировать File.Delete. Это уже не ваша забота. Что стоит протестировать — это факт того, что File.Delete вызывается. Для этого в Visual Studio есть Fake Assemblies.
File.Delete уже оттестирован, и поведение метода детерминировано: либо файл действительно удалится, либо выкинут исключение. Вам достаточно проверить, что ваш код вызывает File.Delete и съедает все исключения. Не надо придумывать ничего сверх этого.Вам достаточно проверить, что ваш код вызывает File.Delete и съедает все исключения
var x = new Form1(); и ожидаете, что есть свободная память, она читаема и не сбоит. Если вы пишете File.Delete(...), то вы ожидаете, что файл действительно будет удалён, либо выкинется исключение. С первым случаем, думаю, все понятно. Вот вам второй случай: выкинулось UnauthorizedAccessException (злобный пользователь нашёл ваш временный файл и поставил ему атрибут read only), файл не удалён. Какой вы сделаете вывод? Правилен ли ваш код? Должен ли валиться тест?Dispose(false)) работу — TaskScheduler.UnobservedTaskException.когда кончатся временные файлыИ объясните, пожалуйста, как могут кончиться временные файлы? :) 65535 файлов — это ограничение
Path.GetTempFileName, но никто не может вам запретить создавать временные файлы другим способом.Path.GetTempFileName — просто обёртка над достаточно глупой функцией, она ничем не лучше собственных временных файлов. Наоборот, а) вы сможете использовать более гибкие имена (например, гуиды; они не кончатся ;), б) вы сможете лучше контролировать время жизни файлов: вместо танцев с тестами финализатора создавайте файлы с FileOptions.DeleteOnClose — сама ОС позаботится, что файл будет удалён, даже если ваш процесс вообще упадёт с ошибкой.б) вы сможете лучше контролировать время жизни файлов: вместо танцев с тестами финализатора создавайте файлы с FileOptions.DeleteOnClose — сама ОС позаботится, что файл будет удалён, даже если ваш процесс вообще упадёт с ошибкой.
Вам не нужно тестировать File.Delete. Это уже не ваша забота. Что стоит протестировать — это факт того, что File.Delete вызывается. Для этого в Visual Studio есть Fake Assemblies.
Вам не нужно тестировать File.Delete. Это уже не ваша забота. Что стоит протестировать — это факт того, что File.Delete вызывается. Для этого в Visual Studio есть Fake Assemblies.пользователя withkittens.
В этот момент никакой финализатор не вызывается, здесь происходит выгрузка из памяти, именно очищение. Вашего объекта в этот момент то уже и нет, объект удалился, когда вы вышли из анонимного метода, где было единственное его упоминание.
нет никаких гарантий что финализатор вообще отработает, а если и отработает, то никто, даже сама платформа, не знает когда он отработает. Следовательно, нужно как то заставить вызвать финализатор. Один из способов, это вызывать выгрузку домайна.
Мне кажется у вас неверно поставлена задача. Как вам уже отвечали в прошлой статье, нет никаких гарантий что финализатор вообще отработает, а если и отработает, то никто, даже сама платформа, не знает когда он отработает.
Как мне помнится, сборщик мусора один на все, и к тому моменту, как у вас подходит дело к проверкt а удален ли файл, финализатор может вообще еще не отработал, и это не значит, что код сломался.
Если вам нужно обязательно удалять файл, тогда требуется использовать патерн Disposable и явным образом вызывать метод Dispose.
use (var file = new TempFile()){
SomeOperations();
}
Как тестировать код финализатора (c#). Послесловие: тест все-таки упал