chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
Hi,
Thanks for previous answer. My next question is: is it possible to mock only one (or selected) instance method.

I want to test method:

public static int ExecuteCommandWithReturnValue(string storedProcedure, ref SqlParameter[] arParams, int commandTimeout, string connectionString)
{
  int returnValue = 0;
   SqlConnection connection = new SqlConnection(connectionString);
   SqlCommand command = new SqlCommand(storedProcedure, connection);
   command.CommandType = CommandType.StoredProcedure;
   command.CommandTimeout = commandTimeout;
      foreach (SqlParameter parameter in arParams)
            {
                command.Parameters.Add(parameter.ParameterName,  parameter.SqlDbType);
                command.Parameters[parameter.ParameterName].Value = parameter.Value;
                command.Parameters[parameter.ParameterName].Direction = parameter.Direction;
            }
   connection.Open();
   command.ExecuteNonQuery();
   returnValue = (int) command.Parameters[0].Value;
   connection.Close();
   return returnValue;
}


and prepare test:

SqlParameter[] arParams = new SqlParameter[] { new SqlParameter("par1", "val1") };
arParams[0].Direction = ParameterDirection.Input;
arParams[0].DbType = DbType.String;
            using (RecordExpectations r = RecorderManager.StartRecording())
            {
                SqlConnection connection = new SqlConnection(null);

                connection.Open();
                //command.ExecuteNonQuery();   how to mock only this method
                //r.Return(2);
                connection.Close();
            }
            Assert.IsInstanceOfType(typeof(int), Common.ExecuteCommandWithReturnValue("storedProcedure", ref arParams, 2, "connectionString"));


I want to "command" instance do all things as is in tested method and only mock invoking command.ExecuteNonQuery. Is it possible?

When i try put in using clausule:

SqlCommand command = new SqlCommand(null,null);


i must mock all "command" invocation also:

command.CommandType = CommandType.StoredProcedure;
command.CommandTimeout = 2;
command.Parameters.Add("par1", SqlDbType.VarChar);
r.Return(new SqlParameter());
command.Parameters["par1"].Value = "val1";
command.Parameters["par1"].Direction = ParameterDirection.Input;


It is lot of unnecessary code, I think.

br
Tadeusz
asked by tlucz (2.9k points)

1 Answer

0 votes
Hi,

What you trying to do is sometimes refereed to as "partial mock".
by default all mocks creating by the isolator are partial, in the sense that if a method with no expectation is called on them they will resort to executing the real code.

the problem you are facing is that when added the:
SqlCommand command = new SqlCommand(null,null);

you have caused the real constructor to be mocked and not executed leaving you with a uninitializoed instance of the sql command.

To solve this issue we need to direct all calls to the "real implementation" including the constructor activation.

Heres an example:
[TestMethod]
[Isolated]
public void FakingASingleCall()
{
    // faking the sqlconnecting (as you can see by default you dont need to do much all void methods
    // are stubbed
    SqlConnection fakeConn = Isolate.Fake.Instance<SqlConnection>();
    Isolate.SwapNextInstance<SqlConnection>().With(fakeConn);

    // faking the command the CallOriginal will direct all calls to the real 
    // implementation except those explicitly specified (in out case ExecuteNonQuery)
    SqlCommand fakeCommand = Isolate.Fake.Instance<SqlCommand>(Members.CallOriginal);
    Isolate.WhenCalled(() => fakeCommand.ExecuteNonQuery()).WillReturn(2);
    Isolate.SwapNextInstance<SqlCommand>().With(fakeCommand);

    // execute the test
    // NOTE - the original value inserted to the SqlParameter was a string - I have fixed that.
    SqlParameter[] arParams = new SqlParameter[] { new SqlParameter("par1", 5) };
    arParams[0].Direction = ParameterDirection.Input;
    arParams[0].DbType = DbType.String;
    int actual = Common.ExecuteCommandWithReturnValue("storedProcedure", ref arParams, 2, "connectionString");
    
    //check that the test returned 5.
    Assert.AreEqual(5, actual); 

}
answered by lior (13.2k points)
...