C# method hiding

  • Thread starter Kenneth Cochran
  • Start date
K

Kenneth Cochran

I'll just start off by saying I'm new to C#, new to unit testing and new to
mock objects.
Ok, I expected the createProcess method in the inherited class to be the one
that gets called by StartDatabaseInstance but that doesn't appear to be the
case. What am I missing?

public bool StartDatabaseInstance(ref string strException)
{
try
{
Process process = createProcess();
ProcessStartInfo pStart = new ProcessStartInfo();

string strFilename = "scm.exe";

string strProgramFiles =
Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles);
string strDefault = Path.Combine(strProgramFiles, "Microsoft SQL
Server\\80\\Tools\\Binn\\scm.exe");
if (File.Exists(strDefault))
{
strFilename = strDefault;
}

pStart.FileName = strFilename;
pStart.Arguments = "*****************************************";
pStart.UseShellExecute = true;
process.StartInfo = pStart;
process.Start();
process.WaitForExit();
return true;
}
catch (Exception ex)
{
strException = ex.Message;
return false;
}
}

public class ChildDatabaseManager:DatabaseManager
{
new protected DynamicMock createProcess()
{
DynamicMock mockProcess = new DynamicMock(typeof(Process));
mockProcess.ExpectAndReturn("Start", true);
mockProcess.ExpectAndReturn("WaitForExit", true);
return mockProcess;
}
}

[TestFixture]
public class DatabaseManagerTests
{
[Test]
public void StartDatabaseInstanceTest()
{
string ExceptionMessage = "";
ChildDatabaseManager DatabaseManagerObject = new
ChildDatabaseManager();
DatabaseManagerObject.StartDatabaseInstance(ref ExceptionMessage);
}
}
 
K

Kenneth Cochran

In case it isn't apparent, what I'm trying to accomplish is rangle the class
into a test harness. In this particular example I'm trying to use "Extract
and Override Factory Method" to break the depenency on
System.Diagnostics.Process.
My original post deglected the definition for createProcess:
protected Process createProcess()
{
return new Process();
}
 
S

Sebastian Hungerecker

Kenneth said:
Ok, I expected the createProcess method in the inherited class to be the
one that gets called by StartDatabaseInstance but that doesn't appear to
be the case. What am I missing?

The method is declared using the "new" keyword, not using the "override"
keyword. As such it does not override the createProcess method of the
parent class, but creates a new, independent one.
That means that any method of the parent class that calls createProcess,
calls the old createProcess method and not the new one which has nothing
to do with old one, except that it happens to have the same name.

HTH,
Sebastian
 
A

Alberto Poblacion

Kenneth Cochran said:
Ok, I expected the createProcess method in the inherited class to be the
one that gets called by StartDatabaseInstance but that doesn't appear to
be the case. What am I missing?

You are calling StartDatabaseInstance on the ChildDatabaseManager class.
This class does not contain a StartDatabaseInstance method; instead, it is
inherited from the parent class, DatabaseManager.
The StartDatabaseInstance method in DatabaseManager, in turn, calls
createProcess(). Since this method is not virtual, and it is not overidden
in the child class, the version of the method that gets executed is the one
that is being directly called (in the DatabaseManager class).

What you are missing is that you need to override the method instead of
hiding it. Hiding the method breaks the chain of inheritance, so you don't
achieve your expected result of calling the version in the child class from
the parent class.
 
K

Kenneth Cochran

Ok, I got it. I was using examples from java. I now remember reading that
methods in java are virtual by default. The C# compiler complained about
missing the 'new' operator so I added it forgetting that C# methods default
to non-virtual.
 
K

Kenneth Cochran

Just on a side note, to test multiple paths through the method I'm reusing
my instance variables in my unit test by assigning null to them then
reinitializing them:

DynamicMock mockProcess = new DynamicMock(typeof(Process));
...

DatabaseManagerObject = null;
mockProcess = null;

mockProcess = new DynamicMock(typeof(Process));
DatabaseManagerObject = new ChildDatabaseManager(mockProcess);
...

Is this the proper way to do this? With a gc is it even necessary?
 
J

Jeff Johnson

Just on a side note, to test multiple paths through the method I'm reusing
my instance variables in my unit test by assigning null to them then
reinitializing them:

DynamicMock mockProcess = new DynamicMock(typeof(Process));
...

DatabaseManagerObject = null;
mockProcess = null;

mockProcess = new DynamicMock(typeof(Process));
DatabaseManagerObject = new ChildDatabaseManager(mockProcess);
...

Is this the proper way to do this? With a gc is it even necessary?

You mean do you have to set a variable to null before setting it to a new
instance of its type? If so, the answer is no. You can just assign a new
instance to the variable and garbage collection will eventually get rid of
the old instance. (Unless you have a disposable object, in which case you
should called Dispose() or wrap it in a using statement.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top