This is a migrated thread and some comments may be shown as answers.

Am I setting up these tests correctly?

3 Answers 101 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Graham
Top achievements
Rank 1
Graham asked on 13 May 2011, 07:50 PM
I am attempting to use JustMocks to unit test our BLL and DAL layer classes, but I am having trouble getting it to work. I suspect that the issue is that I am not setting up the tests properly for the code. Here is a simple example that follows the pattern of the code under test.

First the object
//BO
public class Person
{
    public int ID {get; set;}
    public string name {get; set;}
    public int age {get; set;}
    public bool isMale {get; set;}
}

Then the DAL
//DAL
public class PersonDbo
{
    public static BO.Person GetPersonByID(int ID)
    {
        BO.Person result = new BO.Person();
         
        //Helper method our project uses
        Database db = Helper.CreateDbConnection();
         
        using (DbCommand dbCommand = db.GetStoredProcCommand("dbo.Select_Person_ByID"))
        {
            db.AddInParameter(dbCommand, "@PersonID", DbType.Int32, ID);
             
            using (IDataReader r = db.ExecuteReader(dbCommand))
            {
                if (r.Read())
                {
                    result.ID = r.GetInt32(r.GetOrdinal("PersonID"));
                    result.name = r.GetString(r.GetOrdinal("Name"));
                    result.age = r.GetInt32(r.GetOrdinal("Age"));
                    result.isMale = r.GetBoolean(r.GetOrdinal("Is_Male"));
                }
                else
                    return null;
                return result;
            }
        }
    }
}
 
Then the BLL
//BLL
public class PersonManager
{
    public static BO.Person GetPerson(int ID)
    {
        BO.Person result = PersonDbo.GetPersonByID(ID);
     
        return result;
    }
}

And finally the test
//Test
[TestClass()]
public class PersonManagerTest
{
    [TestMethod()]
    public void GetPersonTest()
    //Arrange
    Person tom = new Person() { ID = 7, name = "Tom", age = 34, isMale = true};
    Mock.SetupStatic<PersonManager>(Behavior.Strict);
    Mock.Arrange(() => PersonManager.GetPerson(7)).Returns(tom).MustBeCalled();
     
    //Act + Assert
    Assert.AreEqual(PersonManager.GetPerson(7), tom);
}

Am I doing these right?

3 Answers, 1 is accepted

Sort by
0
Ricky
Telerik team
answered on 19 May 2011, 03:08 PM
Hi Graham,

Thanks again for bringing up the question. Your test is perfect. However, MustBeCalled is used in conjunction with Mock.Assert where you are checking if your expected call is invoked properly. But since you are doing a strict mock, it will raise mock exception anyway for calls other than the expected.

Therefore, i modified your test in the following way:

[TestMethod()]
public void GetPersonTest()
{
    //Arrange
    Person tom = new Person() { ID = 7, name = "Tom", age = 34, isMale = true };
    Mock.SetupStatic<PersonManager>(Behavior.Strict);
    Mock.Arrange(() => PersonManager.GetPerson(7)).Returns(tom);
    //Act + Assert
    Assert.AreEqual(PersonManager.GetPerson(7), tom);
}

In addition i am mocking static method therefore JustMock full edition should be installed and the profiler should be configured correctly (automatically configured when you check "integrate with visual studio" option during installation).

I am also attaching my test project to let you have a look and i am using the latest official release.

Hope the information is useful.

Kind regards,
Ricky
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Graham
Top achievements
Rank 1
answered on 19 May 2011, 08:14 PM

Another long post, sorry but it is important I get these tests working properly before I make my case to purchase JustMocks to my boss.

For some reason the tests are still hitting the database and pulling actual results rather than the ones I arrange.

I have a custom assertion method that uses reflections to get an array of all the properties of any two objects it is given to compare then asserts they are equal on every elements (our projects have a lot of custom objects that change frequently) and I use this for my unit testing. When I execute something like this:

[TestMethod()] 
public void GetPersonTest() 
    //Arrange 
    Person tom = new Person() { ID = 7, name = "Tom", age = 34, isMale = true }; 
    Mock.SetupStatic<PersonManager>(Behavior.Strict); 
    Mock.Arrange(() => PersonManager.GetPerson(7)).Returns(tom); 
    Person actual;
      
    //Act
    actual = PersonManager.GetPerson(7);
      
    //Assert
    Assert.AreEqual(actual.ID, tom.ID);
    CustomAssert.AreEqual(actual, tom);
}

And the actual database entry for ID = 7 is a 23 year old woman named Sarah, the first assertion will pass but the second will fail. Examining the results show that the actual object has the information for Sarah which could only have come from the database.

I attempted to fix this by also mocking out the DAL layer component like this:
[TestMethod()] 
public void GetPersonTest() 
    //Arrange 
    Person tom = new Person() { ID = 7, name = "Tom", age = 34, isMale = true }; 
    Mock.SetupStatic<PersonManager>(Behavior.Strict);
    Mock.SetupStatic<PersonDbo>(Behavior.Strict);
    Mock.Arrange(() => PersonDbo.GerPersonByID(7).DoNothing(); //This should prevent the database from being called
    Mock.Arrange(() => PersonManager.GetPerson(7)).Returns(tom); //This should set a return value for the test
    Person actual;
      
    //Act
    actual = PersonManager.GetPerson(7);
      
    //Assert
    Assert.AreEqual(actual.ID, tom.ID);
    CustomAssert.AreEqual(actual, tom);
}

But this also fails in the same way. I also tried replacing the DoNothing() call with an explicit Arrange statement:

Mock.Arrange(() => PersonDbo.GerPersonByID(7).Returns(tom);

And THIS failed too. Do you have any idea why the tests are ignoring the mocks and hitting the database anyways?

For completeness here is a simplified version of my CustomAssert.AreEqual() method:

public class CustomAsserts
{
    public static void AreEqual(Object expected, Object actual, string message = "Objects do not match")
    {
        if (expected == null || actual == null)
            Assert.AreEqual(expected, actual, message);
        else
        {
            if (expected.GetType() != actual.GetType())
                Assert.Fail(message);
  
            PropertyInfo[] prop = expected.GetType().GetProperties();
  
            foreach (PropertyInfo property in prop)
            {
                if (property.PropertyType.IsClass && property.PropertyType != typeof(string) && property.PropertyType != typeof(DateTime))
                {
                    CustomAsserts.AreEqual(property.GetValue(expected, null), property.GetValue(actual, null));
                }
                else
                {
                    Assert.AreEqual(property.GetValue(expected, null), property.GetValue(actual, null), message + ": " + property.Name + " does not match");
                }
            }
        }
    }
}
note: this class requires the System.Reflection library.

TL;DR: Mocking out the database but still getting back the actual information on the database. Tried mocking out the DAL layer as well as the BLL layer and still getting live data. Please help.
0
Ricky
Telerik team
answered on 27 May 2011, 09:59 AM
Hi Graham,
Thanks again for the reply. I am re-attaching the test project updating it using the above code and it seems to work nicely.

Please make sure that your profiler is turned on. In case your profiler is not installed correctly or other profiling tool is overriding the target variable. In that regard you could do the following check:

Assert.IsTrue(Mock.IsProfilerEnabled);

Further in order to troubleshoot, you can check the current profiler version as well. For JustMock the profiler variables should look like:

"COR_ENABLE_PROFILING", "0x1"
"COR_PROFILER", "{D1087F67-BEE8-4f53-B27A-4E01F64F3DA8}"
"COMPLUS_ProfAPI_ProfilerCompatibilitySetting", "EnableV2Profiler"

You can compare this with the output from the following lines which you can run inside the vs immediate window during test debug :

System.Environment.GetEnvironmentVariable("COR_ENABLE_PROFILING");  
System.Environment.GetEnvironmentVariable("COR_PROFILER");

In addition please make sure that  other mocking tool that uses profiler is not installed.

Hope this information isuseful.

Kind Regards,
Ricky
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Tags
General Discussions
Asked by
Graham
Top achievements
Rank 1
Answers by
Ricky
Telerik team
Graham
Top achievements
Rank 1
Share this question
or