I'm using MSTest to write test cases for my application.
I have a method where files are moved from one directory to another directory. Now when I run code coverage, it shows that the catch block is not covered in code coverage.
This is my code as below.
class Class1
{
public virtual bool MoveFiles( string fileName)
{
bool retVal = false;
try
{
string sourcePath = "PathSource";
string destinationPath = "DestPath";
if (Directory.Exists(sourcePath) && Directory.Exists(destinationPath))
{
string finalPath = sourcePath + "\\" + fileName ;
if (Directory.Exists(finalPath))
{
File.Move(finalPath, destinationPath);
retVal = true;
}
}
}
catch (Exception ex)
{
LogMessage("Exception Details: " + ex.Message);
retVal = false;
}
return retVal;
}
}
The test method for the above code is this.
[TestMethod()]
public void MoveFilesTest()
{
string filename = "test";
Class1 serviceObj = new Class1();
var result = serviceObj.MoveFiles(filename);
Assert.IsTrue(result);
}
When I run my code coverage, it shows only the try block is covered and not the catch block. So in order to do that, I need to write another test method and generate an exception and test method will look something like this.
[TestMethod()]
public void MoveFilesTest_Exception()
{
string filename = "test";
Class1 serviceObj = new Class1();
ExceptionAssert.Throws<Exception>(() => serviceObj.MoveFiles(filename));
}
Can anyone help to create an exception for this code as I couldn't do that or at least guide me how to do it?
Many thanks!
You can use the Expected Exception Attribute in your tests to indicate that an exception is expected during execution.
The following code will test for invalid characters in the filename and should raise an ArgumentException since > is an invalid character in filenames:
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void InvalidCharacterInFileNameTest()
{
string filename = "test>";
Class1 serviceObj = new Class1();
serviceObj.MoveFiles(filename);
}
Update:
Since the Directory.Exists() 'supresses' any exception that might occur, you also need to change the code in your function to throw an exception if the source file does not exist or is invalid.
This is just an example to show how it can be implemented but your code could look similar to this:
public virtual bool MoveFiles(string fileName)
{
bool retVal = false;
try
{
string sourcePath = "PathSource";
string destinationPath = "DestPath";
if (Directory.Exists(sourcePath) && Directory.Exists(destinationPath))
{
string finalPath = sourcePath + "\\" + fileName;
if (Directory.Exists(finalPath))
{
File.Move(finalPath, destinationPath);
retVal = true;
}
else
{
throw new ArgumentException("Source file does not exists");
}
}
}
catch (Exception ex)
{
LogMessage("Exception Details: " + ex.Message);
retVal = false;
}
return retVal;
}
Related
I have a simple thumbnail function that I wrote for a program that displays pictures and videos in a folder. If it is a video I want to generate a picture to display. Now it is buggy to do this in folders with tons of files so I put it in a try catch statement and just said first try to get the thumbnail, if that doesn't work get the icon, and if that doesn't work just don't display it. Works fine when I debug but when I hammer it with files in production it occasionally crashes. Not surprising since it runs much faster in production. But clearly, since I only have this shellfile function in only one place, the try catch is not catching the exception.
public class Picture : INotifyPropertyChanged
{
private string _path;
private string _thumbpath;
public string ext { get; set; }
public string Thumbpath
{
get
{
if (_thumbpath != "MOVIE!")
{
return _thumbpath;
}
else
{
try
{
Microsoft.WindowsAPICodePack.Shell.ShellFile shellFile = Microsoft.WindowsAPICodePack.Shell.ShellFile.FromFilePath(_path);
System.Drawing.Bitmap bm = shellFile.Thumbnail.Bitmap;
string filename = "RECTHUMB" + RandomString(7) + ".jpg";
bm.Save(temppath + filename, System.Drawing.Imaging.ImageFormat.Jpeg);
bm.Dispose();
return temppath + filename;
}
catch
{
try
{
System.Drawing.Icon icon = System.Drawing.Icon.ExtractAssociatedIcon(_path);
System.Drawing.Bitmap bm = icon.ToBitmap();
string filename = "RECTHUMB" + RandomString(7) + ".jpg";
bm.Save(temppath + filename, System.Drawing.Imaging.ImageFormat.Jpeg);
//bm.Dispose();
return temppath + filename;
}
catch
{
return "";
}
}
}
}
set
{
_thumbpath = value;
}
}
}
Here is the event log:
<EventData><Data>Application: Meta_Data_Mapper.exe CoreCLR Version:
7.0.222.60605 .NET Version: 7.0.2 Description: The process was terminated due to an unhandled exception. Stack: at
Microsoft.WindowsAPICodePack.Shell.IShellItemImageFactory.GetImage(Size,
SIIGBF, IntPtr ByRef) at
Microsoft.WindowsAPICodePack.Shell.ShellThumbnail.GetHBitmap(System.Windows.Size)
at Meta_Data_Mapper.MainWindow+Picture.get_Thumbpath() at ...
Consider a C# code snippet like this (fileexcpt.py):
static void test1()
{
try
{
string text1 = File.ReadAllText(#"dir1\text1.txt");
string text2 = File.ReadAllText("text2.txt");
}
catch (IOException ex)
{
Console.Out.WriteLine(string.Format("Error reading file: {0}", ex.error_filename));
}
}
I hope ex.error_filename or something alike can tell me what file(filepath) caused the IO exception. Can I?
I see examples from https://learn.microsoft.com/en-us/dotnet/standard/io/handling-io-errors, but no such information found.
As for Python, it is natural, like this:
try:
text1 = open(r"dir1\text1.txt", "r").read();
text2 = open("text2.txt", "r").read();
except IOError as ex:
print("Error reading file: {0}".format(ex.filename));
You should avoid programming-by-exception where possible. And when you do need to catch exceptions then isolate the code into a single failing unit - don't catch across multiple points of failure.
Try this, as an example:
static void test1()
{
string text1 = ReadAllTextGuarded(#"dir1\text1.txt");
string text2 = ReadAllTextGuarded("text2.txt");
if (text1 != null & text2 != null)
{
//Success
}
}
static string ReadAllTextGuarded(string filename)
{
try
{
return File.ReadAllText(filename);
}
catch (IOException ex)
{
Console.Out.WriteLine(string.Format("Error reading file: {0}", filename));
}
return null;
}
Why don't you use simply ex whose output's the first line will tell you which gives rise to the error?
try
{
string text1 = File.ReadAllText("text1.txt");
string text2 = File.ReadAllText("text2.txt");
}
catch (FileNotFoundException ex)
{
// If you wish to get absolute path
//Console.Out.WriteLine($"Error reading file: {ex.FileName}");
// relative path
Console.Out.WriteLine($"Error reading file: {ex.FileName.Substring(ex.FileName.LastIndexOf('\\') + 1)}");
// No worry for the Substring exception because LastIndexOf returns -1 if not found, then plus 1 to start from 0.
}
catch (IOException ex)
{
Console.Out.WriteLine($"Error reading file: {ex}");
}
I was previously using the GetFileByServerRelativeUrl and it was working fine, but the characters # and % are not supported while they are supposed to be supported with GetFileByServerRelativePath, so I changed the code as per below but now it just doesn't work with any files???
public bool DownloadFile(string filepath, out string Base64EncodedFile, out string errormessage)
{
Base64EncodedFile = string.Empty;
errormessage = string.Empty;
try
{
Uri filename = new Uri(filepath);
string serverrelative = filename.AbsolutePath;
//This old method does not support # or % but works fine
//Microsoft.SharePoint.Client.File file = context.Web.GetFileByServerRelativeUrl(serverrelative);
// >> Replaced with this
ResourcePath filePathDecoded = ResourcePath.FromDecodedUrl(serverrelative);
Microsoft.SharePoint.Client.File file = context.Web.GetFileByServerRelativePath(filePathDecoded);
// << Replaced with this
context.Load(file);
ClientResult<System.IO.Stream> streamResult = file.OpenBinaryStream();
context.ExecuteQuery();
Base64EncodedFile = ConvertToBase64(streamResult.Value);
return true;
}
catch (Exception ex)
{
errormessage = ex.Message;
return false;
}
}
SharepointClient.SharepointClient newupload = new SharepointClient.SharepointClient("https://xxxxxxx.sharepoint.com/sites/xxxxxxxxx/", usernametext.Text, textpassword.Text);
newupload.DownloadFile(Url.Text, out EncodedAbs, out errormessage);
If I use the old GetFileByServerRelativeUrl it works just fine... I tried everything but I cannot seem to get to work the GetFileByServerRelativePath ... I can't understand what I'm doing wrong???
Please help!!!
My test code for your reference.
using (ClientContext ctx = new ClientContext(targetSiteURL))
{
ctx.Credentials = onlineCredentials;
string fileName = "FileWith#%.docx";
var _File = ctx.Web.GetFileByServerRelativePath(ResourcePath.FromDecodedUrl($"/sites/lee/MyDoc/{fileName}"));
ctx.Load(_File);
ctx.ExecuteQuery();
Console.Write(_File.ServerRelativeUrl);
Console.WriteLine();
}
When I try to debug my code with debugger with F11 (Step Into), my code produced the expected result. When I try to run the code without debugger(without break point), the looping in my code produced unexpected result; to be specific, the looping part only loop for 1 times and terminated, I am confused here, anyone have any idea about this? Below is the loop I mentioned which produced unexpected result.
public bool CopyFileAndFolder(string sourceFolder, string replacePath)
{
bool result = false;
try
{
foreach (string extractPath in Directory.GetDirectories(sourceFolder, "*", SearchOption.AllDirectories))
{
string destFolder = extractPath.Replace(sourceFolder, replacePath);
if (!Directory.Exists(destFolder))
Directory.CreateDirectory(destFolder);
}
foreach (string extractFile in Directory.GetFiles(sourceFolder, "*.*", SearchOption.AllDirectories))
{
string destFile = extractFile.Replace(sourceFolder, replacePath);
File.Copy(extractFile, destFile, true);
}
result = true;
}
catch (Exception)
{
result = false;
}
return result;
}
The complete code, i called the method above with this method:
private bool StartFileRollBackProcess()
{
bool result = false;
string backupFolder = Path.Combine(ConfigurationManager.AppSettings["BackupPath"], completeVersionNumber);
string destBackUpFolder = Directory.GetParent(iisConf.PhysicalPath).FullName;
try
{
DirectoryInfo folderToBeDelete = new DirectoryInfo(destBackUpFolder);
folderToBeDelete.Delete(true);
if (Directory.Exists(backupFolder))
{
Directory.CreateDirectory(destBackUpFolder);
result = CopyFileAndFolder(backupFolder, destBackUpFolder);
if (result)
{
ErrorMsg = "Copy process Failed,Your File has rolled back to previous version";
IsErrorDetected = true;
}
else
{
ErrorMsg = "copy got error";
IsErrorDetected = true;
}
}
}
catch (Exception)
{
ErrorMsg = "Error during roll up process";
IsErrorDetected = true;
}
return result;
}
i have a cloud database server like application on my computer that i'm hosting my game on. However, every time an user tries to save data i get an UnauthorizedAccessException.
Im running it by admin and i dont have any specias right in my folder so i have no idea what's the problem.
Here's my code:
public const string root = "D:/DATABASE/";
public static void WriteData(string playername, string type, string data)
{
if (!Directory.Exists("D:/DATABASE/" + playername))
{
Directory.CreateDirectory("D:/DATABASE/" + playername);
Directory.CreateDirectory("D:/DATABASE/" + playername + "/weapons");
}
if (type != "Weapon")
{
using (StreamWriter sw = new StreamWriter("D:/DATABASE/" + playername + "/" + type + ".sav"))
{
sw.WriteLine(data);
}
}
else
{
string[] dat = data.Split('%');
using (StreamWriter sw = new StreamWriter("D:/DATABASE/" + playername + "/weapons/" + dat[0] + ".gfa"))
{
string[] lines = dat[1].Split('#');
foreach (string cline in lines)
{
sw.WriteLine(cline);
}
}
}
}
public static string ReadLoadout(string playername)
{
string output = "";
string[] items = new string[2];
using (StreamReader sr = new StreamReader(root + playername + "/loadout.gfl"))
{
items[0] = sr.ReadLine();
items[1] = sr.ReadLine();
}
int c = 0;
foreach (string citem in items)
{
if (c > 0) output += "$";
output += citem + "%" + GetCompressedWeaponFile(playername, citem);
c++;
}
return output;
}
public static string GetCompressedWeaponFile(string playerName, string weaponName)
{
string output = "";
using (StreamReader sr = new StreamReader(root + playerName + "/weapons/" + weaponName))
{
string line = " ";
int c = 0;
while (line != null)
{
line = sr.ReadLine();
if (line != null)
{
if (c > 0) output += "#";
output += line;
}
c++;
}
}
return output;
}
public static void RegisterNewUser(string username, string password, string email)
{
string udir = root + username;
Directory.CreateDirectory(udir);
Directory.CreateDirectory(udir + "/weapons");
Directory.CreateDirectory(udir + "/loadouts");
File.WriteAllText(udir + "/password.sav", password);
File.WriteAllText(udir + "/level.sav", "1");
File.WriteAllText(udir + "/money.sav", "1000");
File.WriteAllText(udir + "/email.sav", email);
File.WriteAllText(udir + "/loadout.gfl", "");
using (StreamWriter sw = new StreamWriter(root + "emails.txt", true))
{
sw.WriteLine(email);
}
Email.Send(email, "New Account Registration", string.Format(mailTemplate, username, password));
}
public static void EditLoadout(string username, string items)
{
File.WriteAllLines(root + username + "/loadout.gfl",items.Split('#'));
}
It is difficult to provide specific help without more information. Here are a few of troubleshooting suggestions:
1) Try running your code on a different machine. Specifically your development computer. Do you still have the same error? If not, then there is indeed a permission problem.
2) Have you tried checking the stack trace of the exception?
When you run the application on your own computer, try using the IDE to display the exception. Yes, the problem may ultimately be in a low-level class, but you should be able to break on the error and go back in the call stack to see which method in your code is actually throwing the error.
3) Check the actual exception, even for a system-level exception.
Chances are, if you are able to debug this in the IDE, that you will see property information that will give you a hint. Is it in a directory method or a file write method? Check additional properties. Somewhere it might give you the text of the path (assuming it's a file issue) that it failed on that that could help narrow things down too.
4) Add Exception handling to your code
This is a good rule of thumb, and you should really do this anyway to make a stronger program. Regardless of who's method you are calling (yours, someone else's, or a system method) you need to determine where it should be handled.
For example, in your code, in the RegisterNewUser() method, consider something like:
public static void RegisterNewUser(string username, string password, string email)
{
try
{
string udir = root + username;
Directory.CreateDirectory(udir);
Directory.CreateDirectory(udir + "/weapons");
Directory.CreateDirectory(udir + "/loadouts");
File.WriteAllText(udir + "/password.sav", password);
File.WriteAllText(udir + "/level.sav", "1");
File.WriteAllText(udir + "/money.sav", "1000");
File.WriteAllText(udir + "/email.sav", email);
File.WriteAllText(udir + "/loadout.gfl", "");
using (StreamWriter sw = new StreamWriter(root + "emails.txt", true))
{
sw.WriteLine(email);
}
Email.Send(email, "New Account Registration", string.Format(mailTemplate, username, password));
}
catch (Exception ex)
{
// Create a method to display or log the exception, with it's own error handler
LogAndDisplayExceptions(ex);
// Send the user a message that we failed to add them. Put this in it's own try-catch block
// ideally, for readability, in it's own method.
try
{
Email.Send(email, "Failed to register", "An error occurred while trying to add your account.");
}
catch (Exception exNested)
{
LogAndDisplayExceptions(exNested);
}
}
}
5) Add a "crash-and-burn" exception handler to "main"
In the method that is your "top method" (it's hard to tell in the snippet you provided since there are few methods that would attempt to write to the disk) you could wrap your code in a try - catch block and print the exception or write it to disk.
If you have having trouble writing the exception to disk, I would suggest creating an error file first, make sure that the user account that is running the program can write to it, and then in the catch block open the file for APPEND. This should make it easier to get to the error text.
6) When all else fails, use the Debug class or Console class to write the traditional "I made it to line x."
While this will not solve your problem, it should help you get more information that will provide more insight into where your code is causing an error.